函数 arguments 对象与 call object 之间不得不说的秘密
call object 是作用域链中的概念,在《JS权威指南》第八章。注意:它与Function的call()没有什么关系。这只是个称法而已,而在ECMAscript中换了个名称叫:activation object。
有人早就把 call object 在《JS权威指南》书上的内容部分抄出来了:请见小麦的《作用域链 词法作用域 与 闭包(一)》和Belltoy的《Javascript 的词法作用域、调用对象和闭包》(可能《JS权威指南》中文版把 call object 译为:调用对象)。
犀牛书中应该有对作用域链的很形象的描述
小麦的《作用域链 词法作用域 与 闭包(一)》
这个“应该有”可以看出这篇文章的作者没有看《JS权威指南》,或是翻了下没细看。
看了前面两篇贴文晕了的同学请看下面引用犀牛书中原文内容:
在 JavaScript 解释器调用函数时,首先,函数被定义时,它的作用域链已有效形成。接着,函数添加了一个被称为 call object 或者叫 activation object 的东东到作用域链的前面。call object 初始化了一个引用函数 Arguments 对象的称为 arguments 的属性。然后,call object 添加了函数的取了名称的参数,所有以 var 声明的局部变量也通通加了进去。call object 位于作用域链的头顶,局部变量、函数形参、Arguments 对象都在函数作用域内。也就是说,它们在深入下一层作用域链时肯定会把但凡与之同名的属性掩盖掉。
在 call object 中 this 是关键字而不是属性。
在看《Zakas解答Baranovskiy的JavaScript小测试》(中译)第4解讲 arguments 对象有ECMAscript中的activation object ,于是又想起来了。。
下面引用 ECMA-262 第3版第10.1.8节关于 arguments 对象的内容:
对所有非负整数 arg 小于属性 length 的值来说,带有 ToString(arg) 和它的 attributes(特性) { DontEnum } 的这么个属性会被产生。该属性的初始值是 caller(调用者)所供相应实参值。第一个参数值对应为 arg=0,第二个是 arg=1,等等。当 arg 小于 Function 对象所有形参的数量时,该属性会与相应的 activation object 的属性共同享有其值。也就是说,如果改变该属性的话,相应的 activation object 的属性的值也会改变,反之亦然。
在《精通 JavaScript》的 2.1.2 章节中有 arguments 对象的内容,不过不多。
UPDATE: 国内有某人用“预解析”这么个名字把 call object 与“变量声明会上升到它所在作用域的顶部”连为一体了,请见 Miller《Javascript预解析相关一则》。
(完)