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

ser*_*0ne 4 javascript arrays inheritance prototype

我想子类化一个 javascript 数组并将构造函数参数传递给数组。我所拥有的是:

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

SubArray.prototype = Array.prototype;
Run Code Online (Sandbox Code Playgroud)

测试不表明参数被传递给数组

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

而当我用一个数组来做这件事时,我得到了这个

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

我究竟做错了什么?

Pau*_* S. 5

ES6

在 ES6 中,您可以使用语法扩展Arrayclass

class SubArray extends Array {
    constructor() {
        super(...arguments);
    }
    first() {
        return this[0];
    }
}
Run Code Online (Sandbox Code Playgroud)

长度将按预期工作

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

ES5 之前

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

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

使用 this 不再需要从函数返回new一个Object,并且instanceof将无法确定SubArray

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

ES5(慢)

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

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];};
Run Code Online (Sandbox Code Playgroud)

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

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