为何arguments是类数组对象

为何JavaScript里函数的arguments只是array-like object?

只是标准这么规定的,仍是有什么设计缘由在里面?

JavaScript的函数里面的arguments对象有 .lengh 属性和能够经过 [] 访问,可是确实从Object.prototype继承的。不少时候都会用 Array.prototype.slice.call(arguments) 或者 Array.from(arguments) 转成数组。直接设计成数组不是更好吗?

 

 

这个问题又激起了个人八卦之心!react

在一番寻找以后,找到了彷佛是目前网上仅存的 Brendan Eich 本人探讨 arguments 的资料,是一份录音: (来自 aminutewithbrendan.com 这个已经被关闭的网站,彷佛是和当时的赞助事件调查有关因此被关掉了,可是 archive.org 有存档哈哈)web

大体上,BE 本人也认可 arguments 的设计是由于当时只花了十天因此整得太糙了。在正式规范化 JavaScript 的时候,Microsoft 曾经有人提出把 arguments 改为真正的 Array,BE 本人甚至都打算动手改实现了,可是 MS 那边回去商量了下又回来以为多一事不如少一事,不改了。因而这个糟糕的设计就今后成为了规范... 这是 1997 年的初版 ES 规范。数组

除了 arguments.callee 以外,还有一个神奇的 quirk,那就是 arguments 和实际的参数变量之间的迷之绑定。规范里是这么说的:less

In the case when iarg is less than the number of formal parameters for the function object, this property shares its value with the corresponding property of the activation object. This means that changing this property changes the corresponding property of the activation object and vice versa. The value sharing mechanism depends on the implementation.

换言之,假设一个函数的第一个参数是 a,当你修改 a 的值的时候,arguments[0] 也会同步变化:ide

(function (a) { console.log(arguments[0] === a) // -> true console.log(a) // -> 1 // 修改 arguments arguments[0] = 10 console.log(a) // -> 10 // 修改参数变量 a = 20 console.log(arguments[0]) // -> 20 })(1,2) 

后面的事情你也知道了,ES 规范是要向后兼容的,并且上面的这个 quirk 使得它在引擎实现中须要不少特殊处理,一旦改动,兼容性影响巨大,因此它永远也改不了了。听说在 ES5 讨论时也有人提出要把 arguments 改为 Array 的 subclass,可是很快就不了了之,只是在 strict mode 下对 arguments.callee 和上面的绑定 quirk 进行了限制。直到 ES6 终于对 arguments 提供了一个替代品 - rest parameters:函数

 

function foo (...args) { // 这里 args 终因而真正的 Array 了! } 
BE 本人并无提到为何一开始会把 arguments 设计成对象,所以咱们也只能作猜想。但一个合理的推测是,ES1 里面的 Array.prototype 其实很弱,只有四个方法:toString, join, reverse 和 sort - 连 push, pop, shift, unshift, splice 都没有!而 forEach, filter, map, reduce 这些有用的方法更是 ES5 才添加进来的。因此当时 arguments 就算真的继承自 Array 貌似也没什么大用,因此就这样被放过了... 固然,这只是咱们的猜想,估计 BE 本身今天也说不清本身当时为何这么干的了吧。
相关文章
相关标签/搜索