【问题标题】:Prototype in this Array slice call, why?这个 Array 切片调用中的原型,为什么?
【发布时间】:2011-10-09 11:08:58
【问题描述】:

我正在阅读 JS 函数的 arguments 变量的 MDN 页面:

https://developer.mozilla.org/en/JavaScript/Reference/Functions_and_function_scope/arguments

我知道 arguments 不是数组,所以这不起作用:

var a = arguments.slice();

MDN 上的解决方案是这样做:

var args = Array.prototype.slice.call(arguments);

为什么使用Array.prototype 而不仅仅是Array.slice.call(arguments)?在这里使用原型有意义吗?

【问题讨论】:

    标签: javascript prototype-programming


    【解决方案1】:

    为什么使用 Array.prototype 而不仅仅是 Array.slice.call(arguments)?

    Array.slice 方法是 Array and String Generics 的一部分,Array and String Generics 是一组 “静态” 方法,实现为 ArrayString 构造函数的属性。

    这些方法是非标准的,它们仅在基于 Mozilla 的实现中可用。

    我发现这些方法和标准方法之间存在很多混淆,但如果您进行测试,您应该知道它们并不相同:

    Array.slice === Array.prototype.slice; // false
    

    你会发现它们是不同的方法。

    顺便说一句,如果您使用该方法,则不需要使用call 方法,第一个参数是将用作this 值的对象(Array.slice(arguments))。

    在这里使用原型重要吗?

    是的,Array 构造函数只是一个函数,标准的slice 方法,以及所有其他“数组方法”都在Array.prototype 上定义。

    这个对象,Array.prototype,是所有 Array 对象实例都继承自的对象。

    正如@Pointy 所说,您可以使用 Array 实例获取对该方法的引用:

     [].slice === Array.prototype.slice; // true
    

    理论上,这会创建一个新的 Array 对象,并访问原型链中的 slice 方法,但我记得一些实现开始优化这种属性访问,避免创建 disposable 对象,因此,在某些时候,在性能方面也是完全相同的。

    【讨论】:

    • 这个问题是关于原型继承的,而不是关于Array.slice是否是非标准的。
    • TBH,我认为首先让我感到困惑的是非标准的简写 Array.slice() 调用。
    • @Matt,扩展了我的答案。
    【解决方案2】:

    需要注意的是:

    var argslice = [].slice.call(arguments);
    

    也有效,因为如果“slice”是对 Array 构造函数原型上的函数的引用,那么构造数组上的“slice”(因此)就是相同的函数。

    【讨论】:

      【解决方案3】:

      Array.slice 不存在(至少在 chrome 中不存在)。

      sliceArray 对象原型的一部分,而不是 Array 本身的方法,因此要引用它,您需要通过原型。

      【讨论】:

        【解决方案4】:

        prototype 包含“数组”对象上可用的所有函数。数组本身只指构造函数。因此,您必须从原型中获取函数并将其应用于伪数组“参数”。

        【讨论】:

          【解决方案5】:

          简短回答:是的,prototype 很重要。

          slice 是 Array 对象的 prototype 对象的属性。如果 Array.slice 存在,它将是 Array 构造函数的属性。

          例如,当你写:

          function MyConstructor() {
          ..
          }
          
          MyConstructor.someFunc = function() {
          ..
          }
          

          someFunc 是 MyConstructor 函数对象的一个​​属性,所以这不起作用:

          var obj = new MyConstructor();
          
          obj.someFunc(); // Throws error
          

          但这会:

          MyConstructor.someFunc();
          

          如果您想在所有实例上都有可用的属性,则必须将它们添加到构造函数的 prototype 对象中。例如:

          MyConstructor.prototype.someFunc = function() {
          ..
          };
          

          这将允许您这样做:

          var obj = new MyConstructor();
          
          obj.someFunc();
          

          【讨论】:

            猜你喜欢
            • 2014-05-26
            • 1970-01-01
            • 1970-01-01
            • 2013-07-20
            • 1970-01-01
            • 2018-01-15
            • 2019-12-29
            • 2012-02-21
            • 1970-01-01
            相关资源
            最近更新 更多