子类化JavaScript数组 - 不传递给数组的构造函数参数

时间:2016-01-14 22:49:14

标签: javascript arrays inheritance prototype

我想继承javascript数组并将构造函数参数传递给数组。我所拥有的是:

function SubArray(arguments) {
    Array.apply(this, arguments);
}

SubArray.prototype = Array.prototype;

测试并不表示正在将参数传递给数组

var x = new SubArray("One", "Two", "Three");
// Object[]
// x.length = 0

然而,当我使用数组执行此操作时,我得到了这个

var x = new Array("One", "Two", "Three");
// Object["One", "Two", "Three"]
// x.length = 3

我做错了什么?

1 个答案:

答案 0 :(得分:4)

ES6

在ES6中,您可以使用class语法

扩展 Array
class SubArray extends Array {
    constructor() {
        super(...arguments);
    }
    first() {
        return this[0];
    }
}

长度将按预期工作

var sa = new SubArray('foo', 'bar');
sa[2] = 'baz';
sa.length; // 3
sa.first(); // "foo"
sa instanceof SubArray; // true

预ES5

直到并包括ES5,无法以通常的构造函数原型方式干净地扩展Array而不会丢失功能,而是必须向Array实例添加属性

function SubArray() {
    var arr = Array.apply(null, arguments);
    arr.first = function () {return this[0];};
    return arr;
}

使用此功能不再需要new作为对象从函数返回,instanceof将无法确定 SubArray

var sa = SubArray('foo', 'bar');
sa[2] = 'baz';
sa.length; // 3
sa.first(); // "foo"
sa instanceof SubArray; // false -- this gets broken

ES5(慢)

在行为比速度更重要的ES5环境中,您可以使用Object.setPrototypeOf (see MDN warning)根据需要强制原型链,这是“有点黑客”并且看起来像

function SubArray() {
    var arr = Array.apply(null, arguments);
    Object.setPrototypeOf(arr, SubArray.prototype);
    return arr;
}
SubArray.prototype = Object.create(Array.prototype);
SubArray.prototype.first = function () {return this[0];};

同样,不再需要new,但这次实例的行为与正常扩展的情况完全相同。

var sa = SubArray('foo', 'bar');
sa[2] = 'baz';
sa.length; // 3
sa.first(); // "foo"
sa instanceof SubArray; // true