1.执行环境
执行环境定义了变量或函数有权访问的其它数据,决定了它们各自的行为。每个执行环境都有与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中。
某个执行环境中的所有代码执行完毕后,该环境被销毁,保存在其中的所有变量和函数定义也随之销毁。
每个函数都有自己的执行环境。当执行流进入一个函数时,函数的环境就会被推入一个环境栈中。而在函数执行之后,栈将其环境弹出,把控制权返回给之前的执行环境。
2.作用域链
// 示例 1
function compare(value1, value2) {
if(value1 < value2) {
return -1;
} else if(value1 > value2) {
return 1;
} else {
return 0;
}
}
// undefined
let result = compare(5, 10);
// undefined
result;
// -1
分析示例 1 代码:
先定义了一个 compare()
函数,然后在全局作用域中调用了它。当该函数被调用时,会创建一个执行环境(compare 的执行环境)及相应的作用域链。使用 arguments 和其它命名参数的值来初始化函数的活动对象。在作用域链中,外部函数的活动对象始终处于第二位,...直至作为作用域链终点的全局执行环境。
作用域链本质上是一个指向变量对象的指针列表,它只引用但不实际包含变量对象。
无论什么时候在函数中访问一个变量时,就会从作用域链中搜索具有相应名字的变量。一般来说,当函数执行完毕后,局部活动对象就会被销毁,内存中仅保存全局作用域(全局执行环境的变量对象)。但是,闭包的情况又有所不同。关于闭包在下一章详细介绍。
3.延长作用域链
虽然执行环境的类型只有两种:全局和局部(函数),但还有其它办法来延长作用域链。因为有些语句可以在作用域链的前端临时增加一个变量对象,该变量对象会在代码执行后被移除。
-
try-catch
语句的catch
块 -
with
语句
4.总结
- 执行环境定义了变量或函数有权访问其它数据;
- 每个执行环境都有与之对应的变量对象,环境中定义的所有变量或函数都保存在这个对象中;
- 某个执行环境中的所有代码执行完毕后,该环境会被销毁。保存在其中的变量或函数定义也会被销毁;
- 每个函数都有自己的执行环境,当执行流进入一个函数时,函数的环境被推入一个环境栈中,函数执行后,栈会将其弹出,将控制权返回给之前的执行环境;
- 当代码在一个环境中执行时,会创建变量对象的一个作用域链;
- 作用域链的用途是保证对执行环境有权访问的所有变量和函数的有序访问;
- 每个环境都可以向上搜索作用域链,以查询变量和函数名。
注:文章参考总结自 《JavaScript 高级程序设计》(第 3 版)[美] Nicholas C.Zakas 著 第 73 页。