【问题标题】:Prototyping "arguments" [closed]原型“参数”[关闭]
【发布时间】:2012-08-04 18:30:54
【问题描述】:

简介

我们都知道这些愚蠢的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 字节,并使用 Array.prototype 扩展 arguments 对象的 prototype

所以我终于可以像处理“真实”数组一样处理arguments 对象了。


问题

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

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

【问题讨论】:

    标签: javascript jquery prototypejs mootools


    【解决方案1】:

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

    使用Array.prototype.slicearguments 转换为数组没有任何问题。

    假设我要扩展 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
    }
    

    你可以在here看到这个。

    【讨论】:

    • 其实你是对的,没有注意到。这正是我一直在寻找的......嗯,有时只是有些事情要忘记去想......
    • 这也是迭代整数 for 循环优于 for-in 循环的原因之一(除了性能之外)。虽然您可以在 for-in 中使用 .hasOwnProperty() 方法,但由于潜在的增强原生对象(尤其是 Array 对象),它通常是不安全的。
    • @say2joe for-in 循环用于对象,for 循环用于其他所有内容。
    • @jbabey 不知道你为什么发表那条评论。我认为我的陈述很明显,我知道如何使用循环,但更重要的是,您的陈述非常具有误导性。数组是一个对象......而且,for-in 循环不是迭代数组的最佳实践。如果您的意思是,for-in 循环只能与静态对象文字(例如,基于 JSON 数据的对象)一起使用,那么您的评论是有意义的。
    【解决方案2】:

    有效吗? ;-)

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

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-02-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-10-12
        • 1970-01-01
        • 2015-12-08
        相关资源
        最近更新 更多