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.
js是基于词法作用域的语言:变量的作用域可以理解为定义变量的一系列源代码。全局变量在整个程序中被定义。局部变量在声明它们的函数和该函数嵌套的所有函数中被定义。
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.
如果把局部变量看做一种对象的属性,那么有另一种方法理解变量作用域。每一段js代码都有一个与它相关的作用域链。这个作用域链是一个对象的列表或者链,这组对象定义了在代码作用域中的变量。当js需要查找变量x的的值时,它从链中的第一个对象开始。如果这个对象有名为x的属性,就会用这个属性的值。如果x不是作用域链中所有对象的属性,x不在这段代码的作用域中。
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.
在顶层js代码中,作用域链包含一个单一对象,即全局对象。在一个不嵌套的函数中,作用域链有两个对象。第一个对象定义了函数的参数和局部变量,第二个是全局变量。在一个嵌套函数中,作用域链有更多对象。当一个函数被定义时,它存储了作用域链。当函数被触发时,它创建了一个新的对象来存储它的局部变量,然后将这个新的对象添加到存储的作用域链上,来生成一个更长的新的作用域链。这个作用域链表示作用域。对嵌套函数来说,每当外部函数被调用,内部函数被重新定义。由于作用域链在每次外部函数调用时都不同,内部函数在每次定义时略有不同。内部函数的代码相同,但是作用域链不同。