执行环境
执行环境(execution context, 又称执行上下文) 是JavaScript中最重要的概念, 它定义了变量或函数有权访问的其它数据, 决定它们各自的行为
每个执行环境都有一个与之关联的 变量对象(variable object), 执行环境中定义的所有变量和函数都保存在这个变量对象中
当代码开始执行时, 会进入其当前的执行环境, 在JavaScript中执行环境的类型有两种:
全局环境: 最外围的一个执行环境, 在Web浏览器中指的window对象
局部(函数)环境: 函数被调用执行时, 进入当前函数环境执行代码
函数调用栈
当一个函数执行时, 函数执行环境进入 函数调用栈(call stack, 也可以叫做环境栈), 函数执行完成后, 调用栈将其执行环境弹出, 把控制权交回给之前的执行环境. 因此, 在函数调用栈中, 栈底是全局环境, 栈顶是当前执行环境.
下面用红宝书里的例子和图示演示这个过程:
1 | var color = 'blue'; |
执行环境详解
从上面可以知道, 当一个函数开始执行时, 将会创建一个新的执行环境. 在JavaScript解释器中, 调用一个执行环境会有两个阶段:
创建阶段(当一个函数被调用, 代码执行之前):
- 创建作用域链
- 创建变量对象:
- 建立arguments对象, 检查参数上下文, 初始化属性和值并且创建一个副本+ 检查当前执行环境的函数声明, 在当前变量对象中创建一个属性, 并指向函数引用, 若属性存在, 则修改函数引用指向
- 检查当前执行环境的变量声明, 并在当前变量对象中创建属性, 初始化为
undefined
, 若属性名存在, 则跳过
- 确定
this
的指向
用代码的形式表现的话如下:
1 | executionContextObject = { |
代码执行阶段
赋值, 函数引用和执行代码
代码示例:
1 | function func(i) { |
我们从代码示例中, console.log(typeof foo)
输出的是function
, 而不是undefined
, 是因为函数声明会优先于变量声明, 在检查var foo = 'hello'
的时候, 会发现foo
属性已经在变量对象中存在并跳过.
上面的代码在解释器中可以简单地认为是下面这种形式
1 | function func(i) { |