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

只是标准这么规定的,还是有什么设计原因在里面?

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

 
 

这个问题又激起了我的八卦之心!

在一番寻找之后,找到了似乎是目前网上仅存的 Brendan Eich 本人探讨 arguments 的资料,是一份录音:https://web.archive.org/web/20110822021124/http://minutewith.s3.amazonaws.com/amwb-20101115.mp3 (来自 aminutewithbrendan.com 这个已经被关闭的网站,似乎是和当时的赞助事件调查有关所以被关掉了,但是 archive.org 有存档哈哈)

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

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

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] 也会同步变化:

(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 自己今天也说不清自己当时为什么这么干的了吧。

为什么arguments是类数组对象的更多相关文章

  1. 类数组对象 实参对象arguments

    先看实参对象arguments 之前对argument有点印象,知道它不是真正的数组,但也可以arguments[0]和arguments.length.今天详细的记录一下. js的默认行为:省略的实 ...

  2. (三十六)类数组对象arguments

    类数组对象:arguments 在函数调用时,我们总能见到arguments这个对象,它具体是用来干什么的呢?感觉逼格非常高呢 函数在使用时,我们总会位函数传入各种参数,arguments会将参数储存 ...

  3. 类数组对象:arguments

    在js中调用一个函数的时候,我们经常会给这个函数传递一些参数,js把传入到这个函数的全部参数存储在一个叫做arguments的东西里面,那它到底是什么呢? 一.描述 arguments 是一个对应于传 ...

  4. 类数组对象arguments 和 数组对象

    arguments并不是一个真正的数组,而是一个“类似数组(array-like)”的对象: 就像下面的这段输出,就是典型的类数组对象: {0:12, 1:23} 一.类数组 VS 数组 相同点: 都 ...

  5. 浅谈js的类数组对象arguments

    类数组对象:arguments总所周知,js是一门相当灵活的语言.当我们在js中在调用一个函数的时候,我们经常会给这个函数传递一些参数,js把传入到这个函数的全部参数存储在一个叫做arguments的 ...

  6. 类数组对象与arguments

    类数组对象 所谓的类数组对象: 拥有一个 length 属性和若干索引属性的对象 举个例子: var array = ['name', 'age', 'sex']; var arrayLike = { ...

  7. 类数组对象与 arguments

    类数组对象:拥有一个 length 属性和若干索引属性的对象 var array = ['name', 'age', 'sex']; var arrayLike = { 0: 'name', 1: ' ...

  8. 简述JavaScript对象、数组对象与类数组对象

    问题引出 在上图给出的文档中,用JavaScript获取那个a标签,要用什么办法呢?相信第一反应一定是使用document.getElementsByTagName('a')[0]来获取.同样的,在使 ...

  9. [Effective JavaScript 笔记]第51条:在类数组对象上复用通用的数组方法

    前面有几条都讲过关于Array.prototype的标准方法.这些标准方法被设计成其他对象可复用的方法,即使这些对象并没有继承Array. arguments对象 在22条中提到的函数argument ...

随机推荐

  1. linux 虚拟机模拟配置网络路由环境-简版

    前言:网络路由不管是平常在家里,还是在公司中,都是必需配置的,所以还是非常重要的,今天小编就给大家做个配置网络路由配置的小实验,仅供大家参考.   一.首先,来简单介绍一下网络路由. 1. 网络路由: ...

  2. Druid数据库连接池源码分析

    上一篇文章重点介绍了一下Java的Future模式,最后意淫了一个数据库连接池的场景.本想通过Future模式来防止,当多个线程同时获取数据库连接时各自都生成一个,造成资源浪费.但是忽略了一个根本的功 ...

  3. matplotlib简介及安装

    官网介绍: Matplotlib is a Python 2D plotting library which produces publication quality figures in a var ...

  4. WebUploader上传文件(一)

    写在前面: 文件上传方式很多的,对于大文件的上传,在本次项目中也有涉及,主要是用了分片断点上传大文件.所以就去了解了一下WebUploader,先从简单的上传文件开始吧~ 在代码中写注释,这样看的比较 ...

  5. Mybatis-Oralce批量插入方法

    mybatis-Oralce 中批量插入方法一:<insert id="insertBatchSelective" parameterType="java.util ...

  6. css:background-position > 精灵技术

    background-position : length || length background-position : position || position 取值: length  : 百分数 ...

  7. echarts异步数据加载(在下拉框选择事件中异步更新数据)

    接触echarts 大半年了,从不会到熟练也做过不少的图表,隔了一段时间没使用这玩意,好多东西真心容易忘了.在接触echarts这期间也没有总结什么东西,今天我就来总结一下如何在echart中异步加载 ...

  8. CDQ分治与整体二分小结

    前言 这是一波强行总结. 下面是一波瞎比比. 这几天做了几道CDQ/整体二分,感觉自己做题速度好慢啊. 很多很显然的东西都看不出来 分治分不出来 打不出来 调不对 上午下午晚上的效率完全不一样啊. 完 ...

  9. 从一个word文件中读取所有的表格和标题(2)

    上一篇文章主要讲了从word底层xml中获取表格和标题的方法,但是存在一个问题:word文件必须是docx格式的.如果为doc格式的,可以有两种解决方案: 一.把doc文件转换成docx格式文件,用上 ...

  10. Python 项目实践三(Web应用程序)第五篇

    接着上节继续学习,在这一节,我们将建立一个用户注册和身份验证系统,让用户能够注册账户,进而登录和注销.我们将创建一个新的应用程序,其中包含与处理用户账户相关的所有功能.我们还将对模型Topic稍做修改 ...