作用域(scope)
JavaScript 中的函数属于词法作用域,也就是说函数在它被“定义时”的作用域中运行,而不是在“被执行时”的作用域内运行。
什么是“定义时”? 什么是 “被执行时”?
定义时: 一个函数A在“定义时”就是 function A() { }这个语句执行的时候,就是定义这个函数的时候。
被执行时: A“被执行时”(被调用的时侯)是 A() 这个语句执行的时候。
一个函数的词法作用域是它被定义时它所处的“范围 ”,也就是它外层的“范围”,这个“范围”包含了外层的变量属性,这个“范围”被设置成这个函数的一个内部状态,这个“范围”就是词法作用域。
一个全局函数被定义的时候,全局(这个函数的外层) 的“范围”被设置成这个全局函数的一个内部状态。
一个嵌套函数被定义的时候,被嵌套函数(外层函数) 的“范围”就被设置成这个嵌套函数的一个内部状态。
这个“内部状态” 可以理解成作用域链。
一个函数的作用域是它被定义时所处的“范围” ,那么 JavaScript 里的函数作用域是在函数被定义的时候就确定了,所以它是静态的作用域,词法作用域又称为静态作用域。
调用对象(Call Object)
一个函数的调用对象是动态的,它是在这个函数被调用时,才被实例化的。
我们已经知道,当一个函数被定义的时候,就已经确定了它的作用域链。
当 JavaScript 解释器调用一个函数的时候,它会添加一个新的对象(调用对象) 到这个作用域链的前面。
这个调用对象的一个属性被初始化成一个名叫 arguments 的属性,它引用了这个函数的 Arguments 对象,Arguments 对象是函数的实际参数。
所有用 var 语句声明的本地变量也被定义在这个调用对象里。
这个时候,调用对象处在作用域链的头部,本地变量、函数形式参数和 Arguments 对象全部都在这个函数的范围里了。
当然,这个时候本地变量、函数形式参数和 Arguments 对象就覆盖了作用域链里同名的属性。
......
后面还有