执行上下文
执行上下文:
函数在执行时,会创建一个执行上下文,用来记录函数在哪里执行,函数调用的方法,传入的参数等。执行上下文(execution context,简称:EC)也叫执行“执行环境”。 就是函数解析和执行所在环境的抽象概念。JavaScript 中运行任何的代码都是在执行上下文中运行。
类型:全局上下文、函数执行上下文、eval函数执行上下文
- 全局上下文:是默认的、最基础的执行上下文。不在任何函数中的代码都位于全局执行上下文中。它做了两件事:
- 创建一个全局对象,在浏览器中这个全局对象就是 window 对象。
- 将 this指针指向这个全局对象。一个程序中只能存在一个全局执行上下文。
- 函数执行上下文: 每次调用函数时,都会为该函数创建一个新的执行上下文。每个函数都拥有自己的执行上下文,但是只有在函数被调用的时候才会被创建。一个程序中可以存在任意数量的函数执行上下文
- Eval 函数执行上下文: 运行在 eval 函数中的代码也获得了自己的执行上下文
eval(..) 可以在运行期修改书写期的词法作用域。
词法作用域是在函数在预编译阶段就确定了的,但是eval却在运行时,对词法作用域进行修改,消耗性能。
function foo(str, a) {
eval( str ); // 欺骗!
console.log( a, b ); }
var b = 2;
foo( "var b = 3;", 1 ); // 1, 3
}
类似eval的有,new Function(...),最后一个参数可以接受代码字符串,并将其转 化为动态生成的函数(前面的参数是这个新生成的函数的形参)。
with: 通常被当作重复引用同一个对象中的多个属性的快捷方式,可以不需要重复引用对象本身。
with 可以将一个
没有或有多个属性
的对象处理为一个完全隔离的词法作用域
,因此这个对 象的属性
也会被处理为定义在这个作用域中的词法标识符
。
function foo(obj) {
with (obj) { a = 2; }
}
var o1 = { a: 3 };
var o2 = { b: 3 };
foo( o1 );
console.log( o1.a ); // 2
foo( o2 );
console.log( o2.a ); // undefined
console.log( a ); // 2——不好,a 被泄漏到全局作用域上了!
// o2 的作用域、foo(..) 的作用域和全局作用域中都没有找到标识符 a,因此当 a=2 执行 时,自动创建了一个全局变量(因为是非严格模式)。
执行上下文的生命周期
执行上下文的生命周期包括三个阶段:创建阶段→执行阶段→回收阶段
执行上下文包括:词法环境、变量环境
词法环境组件( LexicalEnvironment component) 和 变量环境组件( VariableEnvironment component)
ExecutionContext = {
ThisBinding = <this value>,
LexicalEnvironment = { ... },
VariableEnvironment = { ... },
}
词法环境
词法环境
是一种规范类型,基于 ECMAScript 代码的词法嵌套结构来定义标识符
和具体变量
或函数
的关联。一个词法环境由环境记录器
和一个可能的引用外部词法环境
的空值组成。
简言之: 词法环境
是一种持有 标识符—变量映射
的结构。这里的 标识符
指的是变量/函数
的名字,而 变量
是对实际对象(包含函数类型对象
)或原始数据
的引用
变量环境
变量环境
它也是一个 词法环境
,所以它有着词法环境的所有特性。
在 ES5 的规范力要单独分出一个变量环境
的概念是为 ES6
服务的: 在 ES6 中,词法环境组件和 变量环境 的一个不同就是前者被用来存储函数声明和变量(let 和 const)绑定
,而后者只用来存储 var 变量绑定
ES5执行上下文
1. 程序启动,全局上下文被创建
- 创建全局上下文的 词法环境
- 创建
对象环境记录器
,它用来定义出现在 全局上下文 中的变量
和函
数的关系(负责处理let
和const
定义的变量)
- 创建
外部环境引用
,值为null
- 创建全局上下文的 变量环境
- 创建
对象环境记录器
,它持有变量声明语句
在执行上下文中创建的绑定关系(负责处理var
定义的变量,初始值为undefined
造成声明提升
)
- 创建
外部环境引用
,值为null
- 确定
this
值为全局对象
(以浏览器为例,就是 window )
2. 函数被调用,函数上下文被创建
- 创建函数上下文的
词法环境
创建
声明式环境记录器
,存储变量
、函数
和参数
,它包含了一个传递给函数的arguments
对象(此对象存储索引和参数的映射
)和传递给函数的参数的length
。(负责处理let
和const
定义的变量)
创建
外部环境引用
,值为全局对
象,或者为父级词法环境(作用域)
- 创建函数上下文的
变量环境
- 创建
声明式环境记录器
,存储变量
、函数
和参数
,它包含了一个传递给函数的arguments
对象(此对象存储索引和参数的映射
)和传递给函数的参数的length
。(负责处理var
定义的变量,初始值为undefined
造成声明提升
)
- 创建
外部环境引用
,值为全局对
象,或者为父级词法环境(作用域)
- 确定
this
值
3. 进入函数执行上下文的执行阶段:
在上下文中运行/解释函数代码,并在代码逐行执行时分配变量值。