扩展本机Array对象,长度可枚举?

时间:2014-02-10 16:25:19

标签: javascript arrays inheritance prototype

这是我的尝试

var extend = function(base, sub) {
    sub.prototype = Object.create(base.prototype);
    sub.prototype.constructor = sub;
};

MyArray = function() {
    Array.call(this, arguments);
};

extend(Array, MyArray);

var arr = new MyArray();

arr.push(1);
arr.push(2);
arr.push(3);

console.log(arr);

for (var i in arr) {
    if (arr.hasOwnProperty(i)) {
        console.log(i + " => " + arr[i]);
    }
}

它正在生成的输出(在节点中运行)

{ '0': 1, '1': 2, '2': 3, length: 3 }
0 => 1
1 => 2
2 => 3
length => 3

我假设通过调用Array.call(this, arguments)

我会将对象的构造传递给本机构造函数,该构造函数应该处理不可枚举的长度。

切换到new Array()时,会生成以下输出。

[ 1, 2, 3 ]
0 => 1
1 => 2
2 => 3

一般问题是为什么结果对象的差异,更具体地说,为什么长度属性可以枚举?

2 个答案:

答案 0 :(得分:2)

  

我假设通过调用Array.call(this, arguments)我会将对象的构造传递给本机构造函数,该构造函数应该处理不可枚举的长度。

没有。 EcmaScript 5 does not allow to subclass Array - 在像节点这样的受控环境中,您只能使用var arr=[]; arr.__proto__=mycustomprototype;黑客。

遗憾的是,{p> Array.call(this)无效。它返回一个新数组,该数组没有任何内容,但它在this上没有做任何事情。您可以this !== Array.call(this)进行检查。

那么你是如何在自定义对象上获得length属性的呢? push确实创造了它。它看到了继承的Array.prototype.length属性(0),因此在插入数字后,它确实分配了arr.length = 1,这创建了一个可枚举的属性。

答案 1 :(得分:0)

通常,避免继承标准类是一种好习惯。原因是有一些属性,例如长度,特别是对内部标记为真实数组的对象进行操作。

使用Array构造函数或数组文字表达式创建的对象将该内部属性设置为“Array”。 Array子类的实例具有[[Class]]属性的“Object”值。请尝试以下

Object.prototype.toString.call(arr); // "[object Object]"

,而

Object.prototype.toString.call([]); // "[object Array]"

这意味着某些Array属性将失去默认行为。