js执行上下文(由浅入深)

每一个函数都有自己的执行上下文EC(执行环境 execution context),并且每个执行上下文中都有它自己的变量对象VO(Variable object),用于存储执行上下文中的变量 、函数声明 、函数参数,这解释了js如何找到我们定义的函数和变量。并且函数是js中唯一一个能创建出作用域的,注意:for,if()else()不能创建作用域。我们通过以下几个例子说明为什么函数和变量的声明会被前置,为什么匿名函数表达式的不可以在外面调用。

var a = 18;
f1();
function f1(){
 var b=9;
 console.log(a);  //undefined
 console.log(b);  //9
 var a = ‘123‘;
}

因为在f1中,在此函数还未执行时变量a,b会被提前声明,也就是说可以理解为下面的代码

var a = 18;
f1();
function f1(){
 var b;
 var a;
 b = 9;
 console.log(a);
 console.log(b);
 a = ‘123‘;
}

如果想进一步理解内部的运行机制,可以用如下方法:

在此案例中,f1函数的作用域链有两个对象,一个是全局变量对象,一个是f1变量对象。

VO (globalContext) = {

  a: 18,

  f1: <ref to function>

}

1.变量初始化阶段

VO (f1 functionContext) = {

  a: undefined,

  b: undefined

}

2.代码执行阶段

VO (f1 functionContext) = {

  a: undefined,

  b: 9

}

再来两个js经典题

function fn(a){
    console.log(a);  //function(){}
    var a = 2;
    function a(){};
    console.log(a); //2
}
fn(1);

我们知道,在运行fn之前,变量和function都会提前声明,但是function会覆盖变量(在不赋值的前提下),

通过以上案例,我们可以总结如下规律:

VO按照如下顺序填充:
 1.  函数参数  (若未传入,初始化该参数值为undefined)
 2.  函数声明  (若发生命名冲突,会覆盖)
 3.  变量声明  (初始化变量值为undefined,若发生命名冲突,会忽略。)

注意:变量初始化(被声明)和变量根本不在一个变量对象里是有区别的,如果用console打印前者会显示undefined,而后者会报一个"ReferenceError: gg is not defined"。

比如

第一个只有一个全局上下文

VO (globalContext) = {

  fn: <ref to function>

}

因为没有执行fn,所以里面的变量读取不到,第二个通过声明被前置,打印undefined.(只有var的变量才能被前置)

为了让大家充分了解执行上下文,再来一个例子。

function test(a,b){ 
var c = 10; 
function d(){} 
var  e = function _e(){}; 
(function x(){}); 
b = 20;  
}   
test(10);

第一阶段——变量初始化阶段如下       第二阶段——代码执行阶段

     

提示:因为此函数中有形参b,所以在变量初始化阶段会b:undefined,如果没有形参b,会报错 b is not defined。

最后来一个压轴的

alert(a);   //undefined
alert(b);   //undefined
alert(x);   //function x(){}
var x = 10;
alert(x);   // 10
x = 20;
function x(){}
alert(x);   // 20
if (true) {
  var a = 1;
} else {
  var b = true;
}
alert(a);   //1
alert(b);   //undefined

首先声明一点,js是没有块级作用域的,所以if{}else{}里面的变量即使不执行,他们的声明也会前置,所以第一个和第二个alert为undefined,对于第三个alert,因为先是x这个变量前置,然后x又变成了function,前面说过了,函数声明如果发生冲突会覆盖变量声明(可以理解为function的优先级更高),所以第三个弹出function,第四个赋值为10,第五个x=20覆盖x=10,第六个因为执行了if,所以给a赋值弹出1,最后一个还是undefined。

时间: 2024-07-31 02:03:50

js执行上下文(由浅入深)的相关文章

一篇文章看懂JS执行上下文

 壹 ? 引 我们都知道,JS代码的执行顺序总是与代码先后顺序有所差异,当先抛开异步问题你会发现就算是同步代码,它的执行也与你的预期不一致,比如: function f1() { console.log('听风是风'); }; f1(); //echo function f1() { console.log('echo'); }; f1(); //echo 按照代码书写顺序,应该先输出 听风是风,再输出 echo才对,很遗憾,两次输出均为 echo:如果我们将上述代码中的函数声明改为函数表达式,

js执行上下文

1.什么是执行上下文 JavaScript是一个单线程语言,意味着同一时间只能执行一个任务.当JavaScript解释器初始化执行代码时, 它首先默认进入全局执行环境(execution context),从此刻开始,函数的每次调用都会创建一个新的执行环境. 2.执行环境的分类 全局环境--JavaScript代码运行时首次进入的环境. 函数环境--当函数被调用时,会进入当前函数中执行代码. Eval--eval内部的文本被执行时(因为eval不被鼓励使用,此处不做详细介绍). 3.执行上下文栈

原型模式故事链(4)--JS执行上下文、变量提升、函数声明

上一章:JS的数据类型 传送门:https://segmentfault.com/a/11... 好!话不多少,我们就开始吧.对变量提升和函数声明的理解,能让你更清楚容易的理解,为什么你的程序报错了~哈哈哈 我们前端的代码一般就三个部分组成html + css +js,一般呢我们的JS又会放在最后执行. 执行上下文:所谓的执行上下文,就是JS代码执行的环境. Javascript中代码的运行环境分为以下三种: 全局上下文 - 这个是默认的代码运行环境,一旦代码被载入,引擎最先进入的就是这个环境.

进阶学习js中的执行上下文

在js中的执行上下文,菜鸟入门基础 这篇文章中我们简单的讲解了js中的上下文,今天我们就更进一步的讲解js中的执行上下文. 1.当遇到变量名和函数名相同的问题. var a = 10; function a(){ console.log(1); } a(); //报错 如果你觉得函数a会覆盖变量a那你肯定是js的新朋友,为什么这里会报错呢?我记得我在基础的执行上下文文章中说过变量声明提前的概念,对这里就是因为这个原因,但是在上面一篇文章中还有一个问题我没有去讲. 那就是函数的声明比变量的声明顺序

Js 作用域与作用域链与执行上下文不得不说的故事 ?(? ???ω??? ?)?

最近在研究Js,发现自己对作用域,作用域链,活动对象这几个概念,理解得不是很清楚,所以拜读了@田小计划大神的博客与其他文章,受益匪浅,写这篇随笔算是自己的读书笔记吧~. 作用域 首先明确一个概念,js只有函数作用域(function-based),没有块级作用域,也就是只有函数会有自己的作用域,其他都没有. 接着,作用域分为全局作用域与局部作用域. 全局作用域中的对象可以在代码的任何地方访问,一般来说,下面情况的对象会在全局作用域中: 最外层函数和在最外层函数外面定义的变量 没有通过关键字"va

js的执行上下文

js中代码有三种类型 : global , function , eval 每一种代码的执行都需要依赖自身的上下文环境 每种代码的执行(程序开始执行,函数被调用,eval代码执行)都会产生一个新的上下文环境,这个上下文环境就称为执行上下(execution context--EC) 执行上下文可以抽象的认为是一个Object,具有一系列属性,其大体结构如下: Execution Context : { variable object : [vars,function declaration,ar

js基础梳理-究竟什么是执行上下文栈(执行栈),执行上下文(可执行代码)?

日常在群里讨论一些概念性的问题,比如变量提升,作用域和闭包相关问题的时候,经常会听一些大佬们给别人解释的时候说执行上下文,调用上下文巴拉巴拉,总有点似懂非懂,不明觉厉的感觉.今天,就对这两个概念梳理一下,加深对js基础核心的理解. 1. 执行上下文(execution context)与可执行代码(execution code) 1.1 首先说一下,可执行代码的类型有哪些: 全局代码:例如加载外部的js文件或者本地标签内的代码.全局代码不包括 function 体内的代码 函数代码:functi

1--面试总结-js深入理解,对象,原型链,构造函数,执行上下文堆栈,执行上下文,变量对象,活动对象,作用域链,闭包,This

参考一手资料:http://dmitrysoshnikov.com/ecmascript/javascript-the-core/中文翻译版本:https://zhuanlan.zhihu.com/p/32042645 Javascript 是一种单线程编程语言,这意味着它只有一个调用栈,call Stack(调用栈 ,,先入后出) 核心:对象,原型链,构造函数,执行上下文堆栈,执行上下文,变量对象,活动对象,作用域链,闭包,This js原型链? 定义 原型对象也是简单的对象并且可以拥有它们自

用实例带你走进this、执行上下文世界[js篇一]

前言: 通过本文你将学习到this的多种用法和使用场景.执行上下文(执行环境)的相关概念. javascript 中this 指向多变.使用场景复杂,也是因其的强大灵活,在前端进阶中也是重要一环,如果能熟练驾驭就能写出更简洁.高质量的代码. 1.执行上下文(执行环境) 在说this之前不得不先说说执行上下文,可以理解为当前代码的执行环境.js中执行环境大概分为三种情况: 全局执行上下文(js运行首次会进入该环境) ---->eg: window对象 函数执行上下文(函数调用) eval JS首次