在JavaScript中创建任意长度的零填充数组最有效的方法是什么?
当前回答
截至ECMAScript2016,大型阵列有一个明确的选择。
由于这一答案在谷歌搜索中仍然排名靠前,所以这里有一个2017年的答案。
这里有一个当前的jsbench,其中有几十种流行的方法,包括迄今为止提出的许多方法。如果你找到更好的方法,请添加、分叉和分享。
我想指出,没有真正最有效的方法来创建任意长度的零填充数组。您可以优化速度,也可以优化清晰度和可维护性——根据项目的需要,两者都可以被视为更有效的选择。
在优化速度时,您需要:使用文字语法创建数组;设置长度,初始化迭代变量,并使用while循环遍历数组。这里有一个例子。
常量arr=[];arr.length=120000;设i=0;而(i<120000){arr[i]=0;i++;}
另一种可能的实施方式是:
(arr = []).length = n;
let i = 0;
while (i < n) {
arr[i] = 0;
i++;
}
但我强烈反对在实践中使用第二次植入,因为它不太清楚,也不允许在数组变量上保持块范围。
这比用for循环填充要快得多,比标准方法快90%左右
const arr = Array(n).fill(0);
但这种填充方法由于其清晰、简洁和可维护性,对于较小的阵列来说仍然是最有效的选择。除非您制作了大量长度为数千或更多的阵列,否则性能差异可能不会让您丧命。
其他一些重要的注意事项。大多数风格指南都建议您在使用ES6或更高版本时,如果没有非常特殊的原因,不要再使用var。对于不会被重新定义的变量使用const,对于会被重新定义变量使用let。MDN和Airbnb的风格指南是获取更多最佳实践信息的好地方。这些问题并不涉及语法,但重要的是,在搜索大量新旧答案时,熟悉JS的人必须了解这些新标准。
其他回答
这个concat版本在我的Chrome测试中要快得多(2013-03-21)。10000000个元素约200ms,而直接初始化为675。
function filledArray(len, value) {
if (len <= 0) return [];
var result = [value];
while (result.length < len/2) {
result = result.concat(result);
}
return result.concat(result.slice(0, len-result.length));
}
另外:如果你想用字符串填充数组,这是一种简洁的方法(虽然没有concat那么快):
function filledArrayString(len, value) {
return new Array(len+1).join(value).split('');
}
我最快的功能是:
function newFilledArray(len, val) {
var a = [];
while(len--){
a.push(val);
}
return a;
}
var st = (new Date()).getTime();
newFilledArray(1000000, 0)
console.log((new Date()).getTime() - st); // returned 63, 65, 62 milliseconds
使用本机push和shift向数组中添加项比声明数组范围并引用每个项来设置其值快得多(大约10倍)。
fyi:在firebug(firefox扩展)中运行时,第一个循环一直在倒计时,我总是会得到更快的时间。
var a = [];
var len = 1000000;
var st = (new Date()).getTime();
while(len){
a.push(0);
len -= 1;
}
console.log((new Date()).getTime() - st); // returned 863, 894, 875 milliseconds
st = (new Date()).getTime();
len = 1000000;
a = [];
for(var i = 0; i < len; i++){
a.push(0);
}
console.log((new Date()).getTime() - st); // returned 1155, 1179, 1163 milliseconds
我很想知道T.J.Crowder对此有何看法?:-)
洛达什:
_.fill(array, value)
是一种干净且跨浏览器安全的填充数组的方法。
ES6溶液:
[...new Array(5)].map(x => 0); // [0, 0, 0, 0, 0]
最快的方法是使用forEach=)
(我们保持IE<9的向后兼容性)
var fillArray = Array.prototype.forEach
? function(arr, n) {
arr.forEach(function(_, index) { arr[index] = n; });
return arr;
}
: function(arr, n) {
var len = arr.length;
arr.length = 0;
while(len--) arr.push(n);
return arr;
};
// test
fillArray([1,2,3], 'X'); // => ['X', 'X', 'X']