这是我的尝试
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
一般问题是为什么结果对象的差异,更具体地说,为什么长度属性可以枚举?
答案 0 :(得分:2)
我假设通过调用
Array.call(this, arguments)
我会将对象的构造传递给本机构造函数,该构造函数应该处理不可枚举的长度。
没有。 EcmaScript 5 does not allow to subclass Array
- 在像节点这样的受控环境中,您只能使用var arr=[]; arr.__proto__=mycustomprototype;
黑客。
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属性将失去默认行为。