我开始尝试原型,然后遇到了一个我不理解的案例。
我正在尝试将一个.fill(val)方法添加到Array原型中。
此代码取自另一个StackOverflow答案:
Array.prototype.fillA = function(val) {
var i;
for (i = 0; i < this.length; i++) {
this[i] = val;
}
return this;
};
看起来我可以用.forEach清理它:
Array.prototype.fillB = function(val) {
this.forEach(function(origVal, i, theArray) {
theArray[i] = val;
});
return this;
};
但这不起作用。 (调用.fillB后,数组尚未更改。)
那么,.fillB究竟出了什么问题?
以下是一些演示此问题的Runnable Snippets:
Array.prototype.fillA = function(val) {
var i;
for (i = 0; i < this.length; i++) {
this[i] = val;
}
return this;
};
var arr,
output;
arr = new Array(5).fillA(5);
alert('arr = "' + arr.join(',') + '"');
Array.prototype.fillB = function(val) {
this.forEach(function(origVal, i, theArray) {
theArray[i] = val;
});
return this;
};
var arr,
output;
arr = new Array(5).fillB(5);
alert('arr = "' + arr.join(',') + '"');
免责声明:
答案 0 :(得分:4)
原因记录为here:
forEach()
按升序为数组中的每个元素执行一次提供的回调。对于已删除或未定义的索引,不会调用它,因为在初始化数组时没有为它们提供任何值。
new Array(5)
创建一个长度为5的数组(所以fillA()
按预期工作),但没有值。
答案 1 :(得分:1)
如果您创建一个类似Array(number)
的数组,那么您创建的数组只有length
属性,并且没有任何元素。
forEach
,map
等为每个实际存在的元素执行函数,忽略length
属性。
使用Array(number)
创建的数组实际上是空的。
如果将几个参数传递给Array
,它将创建一个包含这些参数作为元素的数组。
因此,如果您使用Array.apply(0, Array.call(0, 5))
代替Array(5)
,则会创建一个包含5个undefined
元素的数组。
工作原理:.apply
使用数组作为参数,并使用length属性检查大小。
所以这一行首先用Array.call(0, 5)
创建一个空数组(你可以使用Array(5)
),然后使用length属性查找0,1,2,3,4,5元素,因为它们从未定义过,所以每个值都是undefined
。
换句话说,执行Array.apply(0, Array.call(0, 5))
与执行Array(undefined, undefined, undefined, undefined, undefined)
相同。
Array.prototype.fillB = function(val) {
this.forEach(function(origVal, i, theArray) {
theArray[i] = val;
});
return this;
};
var arr,
output;
arr = Array.apply(0, Array.call(0, 5)).fillB(5);
alert('arr = "' + arr.join(',') + '"');
&#13;
同样,你可以写Array.apply(0, Array(5))
。 (我不是,因为jslint抱怨这种语法)