js 中的 arguments 对象
我一直对函数中的 arguments 对象非常的困惑, 前段时间仔细看了下犀牛书, 才感觉到, arguments 完全就是个坑爹的存在.
好吧, 先小小地解释一下 什么是 arguments , 这个对象只有在函数中才有效, 它的内容是一个当前执行函数的参数数组, 举个例子:
alert(a); // 3
alert(arguments[0]); // 3
alert(arguments[1]); // 6
alert(arguments[2]); // 7
};
test(3,6,7);
这个函数在定义的时候, 只有一个参数 a, 但是调用的时候, 传入了三个参数, 此时的型参a 自然是赋值为3 ,但是另外两个传进来的参数也没有被丢失, 可以通过arguments 数组去访问它们, 传入了多少个参数, arguments对象的长度就为多大. 这个例子中, a 与 arguments[0] 的值实际是同一个对象. 可见在函数中访问参数的方法不止一种.
arguments 对象是一个很管用的对象, 这让javascript 可以很自由地实现可变参, 但是也确实很坑爹, 因为它用起来很像一个数组, 但是从严格意义上将, 它却不是一个数组, 而只是拥有与数组相似的结构而已. 比如做一个很常见的数组分片操作: arguments.slice(3, 4);
这一句代码是一定会报错的, 因为对象不存在这个方法, 我在谷歌浏览器的调试工具中设个断点:
这个例子中, array 是一个普通的数组对象, 可见arguments 对象与普通数组的内部结构还是很像的, 也有length 属性, 但最大的不同就是原型(__proto__)指向的不同, 普通数组是用Array 构造函数生成的, 所以原型直接指向了 Array.prototype 这个对象, 所以可以调用这里面的原生方法, 而arguments 只是一个原始的Object 而已, 所以本身不支持任何数组操作. 不过, 群众的智慧是伟大的, 换种写法, 还是可以用原生的数组方法对arguments 进行操作的, 比如把 arguments.slice(3, 4) 写成Array.prototype.slice.call(arguments, 3, 4);
这里直接访问数组原型中的slice 方法, 并把arguments 作为this 传进去, 这就像arguments自己去调用这个方法一样. slice 究竟是怎么执行的我们不知道, 但是猜也猜得出, 不过就是对内部元素的一些操作, 由于 arguments 内部结构和一个普通数组差不了多少, 所以这个方法对arguments 也是可用的. 其他数组方法也是一样的道理.