3

介绍

我们都知道这些愚蠢arguments的 JavaScript 函数对象。

但为什么反对?不是数组吗?

不,不是,这就是为什么很多人称其为 JavaScript 概念的失败:

(function () {
    return arguments.slice(); // TypeError: arguments.slice is not a function
}());

意图

好的,这只是我想问的真实情况的介绍,但在问之前您需要更多信息:

在最后几天阅读不同的代码时,在很多地方看到以下代码行时,我感到非常害怕。

args = Array.prototype.slice(arguments);

所以,它的作用是简单地将arguments对象“转换”为包含所有原型和内容的数组。


我的解决方案

我想到的是:虽然 JavaScript 都是关于原型设计的,但我们为什么不扩展arguments对象prototype本身呢?我检查了一些网站的现有脚本,但没有发现任何我想要找到的东西,最后我自己写了:

(function () {
    var i, methods;

    arguments.constructor.prototype = Array.prototype;
    methods = ['concat', 'join', 'pop', 'push', 'reverse', 'shift', 'slice', 'sort', 'splice', 'toString', 'unshift'];

    for (i = 0; i < methods.length; i += 1) {
        if (arguments.constructor.prototype.hasOwnProperty(methods[i]) === false) {
            arguments.constructor.prototype[methods[i]] = Array.prototype[methods[i]];
        }
    }
}());

压缩后它只需要 260 字节,并arguments通过prototype使用Array.prototype.

所以最后我可以像处理arguments“真实”数组一样处理对象。


问题

在检查了最著名的 JavaScript 框架后,我完成了以下操作:没有使用这种结构并扩展了arguments对象的prototype.

但为什么?有什么问题吗,我现在没有想到?

4

3 回答 3

5

arguments对象不是类型,它是泛型的Object。为了扩展它的原型,您必须扩展 的原型Object,这通常不是一个好主意。

arguments使用 . 转换为 Array没有任何问题Array.prototype.slice

假设我要扩展arguments原型:

arguments.constructor.prototype.foo = 'bar';

这里的问题是这arguments.constructor不是某个Argument对象,它只是Object. 现在,如果我尝试做一些应该正常工作的事情,那就太可怕了:

var someNewObject = {
    someProperty: 'someValue'
};

for (var item in someNewObject) {
    console.log(item);  // logs someProperty AND foo, not good
}

您可以在这里看到这一点。

于 2012-08-07T17:40:11.773 回答
2

通常,大多数人都回避更改 ECMAScript/JavaScript 原生对象。就个人而言,我喜欢你的方法(它聪明而有用);但是,当您将代码引入更大的项目时,就会引入问题。当浏览器对 Array(本机)对象的实现不同于标准并且其他代码库(如 jQuery)以特定的期望处理该对象时,可能会出现意想不到的后果。但是,如果 jQuery 期望函数的参数属性 (/object) 是某种类型并且它已被更改,例如被您的代码更改,那么您很可能会破坏像 jQuery 这样的广泛使用的库。

于 2012-08-07T17:37:44.010 回答
0

它有效吗?;-)

如果是这样,我认为你已经实现了你想要的。但是,arguments 不是数组的一个原因可能是 arguments 变量并不意味着像普通变量一样四处传播。它只能在函数体内访问,然后被丢弃。因此,我不知道当它突然变成一个数组时会发生什么。

除此之外,聪明的解决方案!

于 2012-08-07T17:39:57.700 回答