目录
3.作用域链增强Scope Chain Augmentation
4.1使用 var 的函数作用域声明 Function Scope Declaration Using var
4.2 使用 let 的块级作用域声明 Block Scope Declaration Using let
4.3 使用 const 的常量声明Constant Declaration Using const
1.执行上下文
执行上下文(以下简称“上下文”)execution context
变量或函数的上下文决定了它们可以访问哪些数据,以及它们的行为。The execution context of a variable or function defines what other data it has access to, as well as how it should behave
每个上下文都有一个关联的变量对象(variable object),而这个上下文中定义的所有变量和函数都存在于这个对象上。
虽然无法通过代码访问变量对象,但后台处理数据会用到它。
全局上下文global execution context是最外层的上下文。
根据 ECMAScript 实现的宿主环境host environment for an ECMAScript implementation,表示全局上下文的对象可能不一样。
在浏览器中,全局上下文就是我们常说的 window 对象,因此所有通过 var 定义的全局变量和函数都会成为 window 对象的属性和方法。
上下文在其所有代码都执行完毕后会被销毁,包括定义在它上面的所有变量和函数 When an execution context has executed all of its code, it is destroyed, taking with it all of the variables and functions defined within it
全局上下文在应用程序退出前才会被销毁,比如关闭网页或退出浏览器
每个函数调用function call都有自己的上下文。当代码执行流进入函数时Whenever code execution flows into a function,函数的上下文被推到一个上下文栈上context stack。
在函数执行完之后,上下文栈会弹出该函数上下文,将控制权返还给之前的执行上下文。
ECMAScript程序的执行流就是通过这个上下文栈进行控制的。
2.作用域链
上下文中的代码在执行的时候,会创建变量对象的一个作用域链(scope chain)。When code is executed in a context, a scope chain of variable objects is created
这个作用域链决定了各级上下文中的代码在访问变量和函数时的顺序。The purpose of the scope chain is to provide ordered access to all variables and functions that an execution context has access to.
代码正在执行的上下文的变量对象始终位于作用域链的最前端。The front of the scope chain is always the variable object of the context whose code is executing
如果上下文是函数,则其活动对象(activation object)用作变量对象。活动对象最初只有一个定义变量:arguments。
If the context is a function, then the activation object is used as the variable object
作用域链中的下一个变量对象来自包含上下文,再下一个对象来自再下一个包含上下文。以此类推直至全局上下文;The next variable object in the chain is from the containing context, and the next after that is from the next containing context. This pattern continues until the global context is reached
全局上下文的变量对象始终是作用域链的最后一个变量对象 the global context’s variable object is always the last of the scope chain
代码执行时的标识符解析是通过沿作用域链逐级搜索标识符名称完成的。Identifiers are resolved by navigating the scope chain in search of the identifier name
搜索过程始终从作用域链的最前端开始,然后逐级往后,直到找到标识符。(如果没有找到标识符,那么通常会报错。)
The search always begins at the front of the chain and proceeds to the back until the identifier is found. (If the identifier isn’t found, typically an error occurs.)
var color = "blue";
function changeColor() {
if (color === "blue") {
color = "red";
} else {
color = "blue";
}
}
changeColor();
//函数 changeColor()的作用域链包含两个对象:一个是它自己的变量对象(就是定义 arguments 对象的那个)the function changeColor() has a scope chain with two objects in it: its own variable object (upon which the arguments object is defined)
//另一个是全局上下文的变量对象。
//这个函数内部之所以能够访问变量color,就是因为可以在作用域链中找到它。The variable color is therefore accessible inside the function, because it can be found in the scope chain
<