3.10.3 The Scope Chain
JavaScript is a lexically scoped language: the scope of a variable can be thought of as the set of source code lines for which the variable is defined. Global variables are defined throughout the program.
Local variables are defined throughout the function in which they are declared, and also within any functions nested within that function.
If we think of local variables as properties of some kind of implementation-defined object, then there is another way to think about variable scope. Every chunk of Java-Script code (global code or functions) has a scope chain associated with it. This scope chain is a list or chain of objects that defines the variables that are “in scope” for that code. When JavaScript needs to look up the value of a variable x (a process called variable resolution), it starts by looking at the first object in the chain. If that object has a property named x, the value of that property is used. If the first object does not have a property named x, JavaScript continues the search with the next object in the chain. If
the second object does not have a property named x, the search moves on
to the next object, and so on. If x is not a property of any of the
objects in the scope chain, then x is not in scope for that code, and a ReferenceError occurs.
In top-level JavaScript code (i.e., code not contained within any function definitions), the scope chain consists of a single object, the global object. In a non-nested function, the scope chain consists of two objects. The first is the object that defines the function’s parameters and local variables, and the second is the global object. In a nested function, the
scope chain has three or more objects. It is important to understand
how this chain of objects is created. When a function is defined, it
stores the scope chain then in effect.(当函数被定义的时候,被定义的函数保存了正起作用的作用域链。)
When
that function is invoked, it creates a new object to store its local
variables, and adds that new object to the stored scope chain to create a
new, longer, chain that represents the scope for that function
invocation.(当函数被调用的时候,该函数创建了一个新的对象(这个对象保存了函数参数及内部变量),并把它添加到已保存的作用域链中,这样为
该函数创建了一个新的作用域链,替代了原来保存的作用域链。) This becomes more interesting for nested functions because each time the outer function is called, the inner function is defined again. Since the scope chain differs on each invocation of the outer function, the inner function will be subtly different each time it is defined—the code of the inner function will be identical on each invocation of the outer function, but the scope chain associated with that code will be different.
This notion of a scope chain is helpful for understanding the with statement (§5.7.1) and is crucial for understanding closures (§8.6).