关键词:
执行上下文、词法环境、变量环境、this、执行上下文栈、变量对象、作用域链
Execution Content 执行上下文
执行上下文定义了变量或函数有权访问的其他数据,决定了他们各自的行为。当javascript代码执行一段可执行代码时,会创建对应的执行上下文; 代码全部执行完后,该执行上下文也会被销毁,保存在其中的变量和函数定义也随之被销毁。执行上下文会管理代码执行过程中使用的内存。
执行上下文分3种:
- Global-Execution-Content 全局执行上下文
在web浏览器中,全局执行上下文就是window对象 - Function-Execution-Content 函数执行上下文
每次调用函数时,都会创建一个函数执行上下文 - eval执行上下文
创建执行上下文
javascript引擎创建执行上下文有两个阶段:
- 创建阶段
- this绑定
- 创建词法环境 Lexical-Environment
- 创建变量环境 Variable-Environment
- 执行阶段
this绑定
在全局执行上下文中,this指向全局对象(浏览器中指window对象);
在函数执行上下文中,this的值取决于函数是如何并调用的。如果函数被一个引用对象调用,那么this会被设置成这个对象,否则this会被设置为window或undefined(严格模式下)
var obj = {
getThis: function(){
return this
}
}
obj.getThis(); // obj
var fn = obj.getThis
fn(); // window
词法环境 Lexical-Environment
词法环境是一种规范类型,基于ECMAScript代码的词法嵌套结构来定义“标识符”和具体函数和变量的关系。存储let,const 定义的函数声明和变量绑定
一个词法环境由一个环境记录器和一个(可能存在的)对外部词法环境的引用组成。
- 环境记录器
环境记录器存储变量和函数声明的具体位置。
函数执行环境中环境记录器为声明式环境记录器,存储变量、函数、和函数参数,声明式环境记录器包含一个传递给函数的argument对象;
全局执行环境中的环境记录器为对象环境记录器,定义出现在全局执行上下文中的变量和函数的关系。 - 对外部词法环境的引用
通过这个引用可以访问父级词法环境
变量环境 Variable-Environment
变量环境其实也是一个词法环境,用来存储变量声明语句在执行上下文中创建的绑定关系,即,存储var声明的变量的绑定
在创建阶段,let、const定义的变量变量没有关联任何值,但是var声明的变量会被设置为undefined,所以var变量在声明之前访问值为undefined,但不会报错,即变量声明提升。let、const变量声明前访问会导致引用错误。
执行阶段
执行阶段完成对所有变量的分配,并执行代码。
Execution Content Stack 执行上下文栈ECS
javascript引擎创建执行上下文栈管理执行代码是创建的所有执行上下文。
当JavaScript脚本第一次执行代码时,会创建一个全局执行上下文,并压入执行栈;之后每次调用函数时,会为该函数创建一个函数执行上下文并压入栈,当函数执行结束,对应当执行上下文从栈中弹出。
下面两段代码的执行结果一样"local",但是执行上下文栈的变化不同。
var scope = "global";
function checkScope(){
var scope = "local";
function fn(){
return scope;
}
return fn();
}
checkScope();
// 方法执行时 执行上下文栈的变化如下
ESCStack.push(<checkScope> function-Context)
ESCStack.push(<fn> function-Context)
ESCStack.pop()
ESCStack.pop()
var scope = "global";
function checkScope(){
var scope = "local";
function fn(){
return scope;
}
return fn;
}
checkScope()();
// 方法执行时 执行上下文栈的变化如下
ESCStack.push(<checkScope> function-Context)
ESCStack.pop()
ESCStack.push(<fn> function-Context)
ESCStack.pop()
JavaScript函数执行时用到作用域链,作用域链是在函数定义时创建的。
执行上下文的重要特性
- 变量对象 Variable Object
- 作用域链 Scope Chain
- this
变量对象 Variable-Object
变量对象是与执行上下文相关的数据作用域,存储在上下文中定义的变量和函数声明。
全局执行上下文中的变量对象就是全局对象,在浏览器中全局对象就是window对象。
在函数执行上下文中,用**活动对象(Activation-Object)**表示比变量对象。互动对象在进入函数执行上下文时被创建,它通过函数的arguments属性初始化。
变量对象包括函数的所有形参、函数声明(function)、变量声明(var)。如果变量名称和已经声明的形参或函数名称相同,变量声明不会干扰已经存在的这类属性。
作用域链 Scope-Chain
作用域链保证对执行上下文有权访问的所有变量和函数的有序访问。
作用域的前端,始终是当前执行代码所在执行环境的变量对象;作用域的最后一个对象,始终是全局执行上下文的变量对象。
标识符解析是从作用域链的前端开始,逐层向上搜索标识符的过程。