阵列set​​PrototypeOf继承 [英] Array subclassing with setPrototypeOf

查看:301
本文介绍了阵列set​​PrototypeOf继承的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以,我读了一些博客文章,所以线程和有关的子类化阵列在JavaScript中。在话题的普遍看法是,有没有方法来创建具有某种缺点的子类。

So I read some blog posts, SO threads and other lectures about subclassing Array in JavaScript. The general view on the topic is that there is no way to create a subclass with some kind of downside.

虽然尝试了一些事情,我想出了这个解决方案为我自己:

While trying out a few things I came up with this solution for myself:

// This is the constructor of the new class.
function CustomArray() {

    // The "use strict" statement changes the way the "magic" variable
    // "arguments" works and makes code generally safer.
    "use strict";

    // Create an actual array. This way the object will treat numeric
    // properties in the special way it is supposed to.
    var arr = [],
        i;

    // Overwrite the object's prototype, so that CustomArray.prototype is
    // in the prototype chain and the object inherits its methods. This does
    // not break the special behaviour of arrays.
    Object.setPrototypeOf(arr, CustomArray.prototype);

    // Take all arguments and push them to the array.
    for (i = 0; i < arguments.length; i++) {
        arr.push(arguments[i]);
    }

    // Return the array with the modified prototype chain. This overwrites
    // the return value of the constructor so that CustomArray() really
    // returns the modified array and not "this".
    return arr;
}

// Make CustomArray inherit from Array.
CustomArray.prototype = Object.create(Array.prototype);

// Define a method for the CustomArray class.
CustomArray.prototype.last = function () {
    return this[this.length - 1];
};

var myArray = new CustomArray("A", "B", 3);
// [ "A", "B", 3 ]

myArray.length;
// 3

myArray.push("C");
// [ "A", "B", 3, "C" ]

myArray.length;
// 4

myArray.last();
// "C"

我的问题是:有什么不对的code?我觉得很难相信,我想出了一解经过这么多的人在我之前搜索。

My question is: Is there anything wrong with this code? I find it hard to believe that I came up with "the one solution" after so many people searched before me.

推荐答案

本文讨论了如何创建一个数组子类。也就是说,我们要创建一个具有 Array.prototype 在其原型链的对象,但是有一个直接的原型父母不在 Array.prototype (即,以使原型家长可以提供超出阵列原型附加方法)。

The article discusses how to create an array "subclass". That is, we want to create an object that has Array.prototype in its prototype chain, but with an immediate prototype parent that is not Array.prototype (i.e., so that the prototype parent can provide additional methods beyond the array prototype).

这文章说,在创建数组子的基本困难是,从阵列得到他们的行为的两个

That article says that a fundamental difficulty in creating an array "subclass" is that arrays get their behavior from both


  1. 的原型,

  2. 仅仅是阵列实例。

如果阵列继承了他们从 Array.prototype 所有的行为,我们的工作会非常快。我们将简单地创建一个对象,其原型链包括 Array.prototype 。该对象将成为一个理想的原型为我们的阵列的子类的实例。

If arrays inherited all their behavior from Array.prototype, our work would be very quick. We would simply create an object whose prototype chain includes Array.prototype. That object would make an ideal prototype for our array-subclass instances.

然而,阵列具有是的特殊的自动行为特有阵列实例的,并且不会从原型继承。 (特别是,我的意思是围绕长度财产行为自动更改当数组的变化,反之亦然。)这是提供给每个数组实例的行为,当它被创建在阵列构造函数,也没有办法如实模仿他们的ECMAScript 5。因此,阵列子类的实例的必须最初是由<$ C创建$ C>阵列构造的。这是不可转让的,如果我们要适当的长度的行为。

However, arrays have special automatic behaviors that are unique to array instances, and are not inherited from the prototype. (In particular, I mean the behaviors around the length property automatically changing when the array changes, and vice versa.) These are behaviors supplied to each array instance when it is created by the Array constructor, and there is no way to mimic them faithfully in ECMAScript 5. Therefore, the instance of your array subclass must be originally created by the Array constructor. This is non-negotiable, if we want the appropriate length behaviors.

这与我们的其他条件要求的冲突,该实例必须有一个原型,是不是 Array.prototype 。 (我们不希望给方法添加到 Array.prototype ;我们希望的方法添加到使用对象 Array.prototype 作为自己的原型。)在ECMAScript中5,任何物体使用阵列构造必须具有 Array.prototype 。 ECMAScript的5规范提供任何机制在创建后更改对象的原型。

This requirement conflicts with our other requirement that the instance must have a prototype that is not Array.prototype. (We don't want to add methods to Array.prototype; we want to add methods to an object that uses Array.prototype as its own prototype .) In ECMAScript 5, any object created using the Array constructor must have the prototype parent of Array.prototype. The ECMAScript 5 spec provides no mechanism to change an object's prototype after it is created.

相反,ECMAScript的6确实提供这样的机制。你的做法是相当类似 __ __原的文章中所描述的方法为基础,根据部分<一个href=\"http://perfectionkills.com/how-ecmascript-5-still-does-not-allow-to-subclass-an-array/#wrappers_prototype_chain_injection\"相对=nofollow> 包装器。原型链注入。的,除了你使用的ECMAScript 6的 Object.setPrototypeOf 而不是 __ __原

By contrast, ECMAScript 6 does provide such a mechanism. Your approach is quite similar to the __proto__-based approach described in the article, under the section "Wrappers. Prototype chain injection.," except you use ECMAScript 6's Object.setPrototypeOf instead of __proto__.

您正确的解决方案满足所有的下列要求:

Your solution correctly satisfies all of the following requirements:


  1. 每个实例实际上是一个数组(即,已被阵列构造构造)。这确保了 [等级] 内部属性是正确的,而长度正确行为。

  2. 每个实例有一个直接原型不是 Array.prototype ,但仍包含 Array.prototype 在其原型链中。

  1. Each instance actually is an array (i.e., has been constructed by the Array constructor). This ensures that the [[Class]] internal property is correct, and length behaves correctly.
  2. Each instance has an immediate prototype that is not Array.prototype, but still includes Array.prototype in its prototype chain.

这些要求是previously不可能ES5满足,但ES6使得它很容易。在ES5,你可以有不符合要求的#2,或不能满足要求#1的纯对象的数组实例。

These requirements were previously impossible to satisfy in ES5, but ES6 makes it fairly easy. In ES5, you could have an array instance that fails to satisfy requirement #2, or a plain object that fails to satisfy requirement #1.

这篇关于阵列set​​PrototypeOf继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆