How to initialize an array's length in javascript?
我在javascript(包括w3schools和devguru)中阅读过的大多数教程都建议您可以通过使用
在JS文件中大量使用了这种语法之后,我通过JSlint运行了其中一个文件,它吓坏了:
Error: Problem at line 1 character 22: Expected ')' and instead saw '4'.
var test = new Array(4);
Problem at line 1 character 23: Expected ';' and instead saw ')'.
var test = new Array(4);
Problem at line 1 character 23: Expected an identifier and instead saw ')'.
号
在阅读了JSlint对其行为的解释之后,JSlint似乎并不真正喜欢
所以我有几个问题。首先,为什么?我使用
1 2 | var test = []; test.length = 4; |
Array(5) 为您提供了一个长度为5但没有值的数组,因此您不能对它进行迭代。Array.apply(null, Array(5)).map(function () {}) 为您提供了一个长度为5且未定义为值的数组,现在可以对其进行迭代。Array.apply(null, Array(5)).map(function (x, i) { return i; }) 为您提供了一个长度为5、值为0、1、2、3、4的数组。Array(5).forEach(alert) 什么也不做,Array.apply(null, Array(5)).forEach(alert) 给你5个提示ES6 给了我们Array.from 所以现在你也可以使用Array.from(Array(5)).forEach(alert) 。如果您想用某个值初始化,这些很好地知道…江户十一〔22〕、江户十一〔23〕。或
Array.from({length: 5}, (v, i) => i) // gives [0, 1, 2, 3, 4] 。为什么要初始化长度?理论上没有必要这样做。它甚至可能导致混淆行为,因为所有使用
length 来查明数组是否为空的测试都将报告数组不是空的。一些测试表明,如果随后填充数组,则设置大型数组的初始长度可能更有效,但不同浏览器的性能增益(如果有)似乎有所不同。JSlint不喜欢
new Array() ,因为构造者不明确。1new Array(4);创建长度为4的空数组。但是
1new Array('4');号
创建一个包含值
'4' 的数组。- 此方法与其他方法一样长时间用于对函数的第一次调用,但很少时间用于以后的调用(除非要求更大的数组)。
standard 阵列永久性地保留了与您所要求的最大阵列相同的空间。
小精灵
关于您的注释:在JS中,您不需要初始化数组的长度。它是动态增长的。您可以将长度存储在某个变量中,例如
1 2 3 4 5 6 | var data = []; var length = 5; // user defined length for(var i = 0; i < length; i++) { data.push(createSomeObject()); } |
使用ES2015
1 2 3 | // `n` is the size you want to initialize your array // `0` is what the array will be filled with (can be any other value) Array(n).fill(0) |
。
比
可以将
最短的:
1 | [...Array(1000)] |
。
1 2 3 | [...Array(6)].map(x=>0); // [0, 0, 0, 0, 0, 0] |
或
1 2 3 | Array(6).fill(0); // [0, 0, 0, 0, 0, 0] |
。
注:不能循环空槽
或
1 2 3 | Array(6).fill(null).map( (x,i) => i ); // [0, 1, 2, 3, 4, 5] |
(字体安全)
创建嵌套数组用
1 2 3 4 5 | var a = Array(3).fill([6]); // [[6], [6], [6]] a[ 0 ].push( 9 ); // [[6,9], [6,9], [6,9]] |
。
解决方案
1 2 3 4 | var a = [...Array(3)].map(x=>[]); a[ 0 ].push( 4, 2 ); // [[4,2], [ ], [ ]] |
号
因此,3x2阵列将如下所示:
1 2 3 4 5 | [...Array(3)].map(x=>Array(2).fill(0)); // [ [0,0] , // [0,0] , // [0,0] ] |
号
ES6引入了
1 2 | Array.from({length: 10}, (x, i) => i); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] |
。
在这种情况下,
这将把长度属性初始化为4:
1 | var x = [,,,,]; |
。
我很惊讶没有一个功能性的解决方案建议您将长度设置为一行。以下基于下划线:
1 2 | var test = _.map(_.range(4), function () { return undefined; }); console.log(test.length); |
出于上面提到的原因,我将避免这样做,除非我想将数组初始化为特定的值。值得注意的是,还有其他实现范围的库,包括lo dash和lazy,它们可能具有不同的性能特征。
(作为评论,这可能更好,但时间太长了)
所以,在阅读了这篇文章之后,我很好奇预分配是否真的更快,因为理论上它应该更快。然而,这个博客给出了一些建议,反对它http://www.html5rocks.com/en/tutorials/speed/v8/。
所以还是不确定,我把它放在测试中。事实证明,它似乎更慢。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | var time = Date.now(); var temp = []; for(var i=0;i<100000;i++){ temp[i]=i; } console.log(Date.now()-time); var time = Date.now(); var temp2 = new Array(100000); for(var i=0;i<100000;i++){ temp2[i] = i; } console.log(Date.now()-time); |
此代码在几次偶然运行后生成以下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | $ node main.js 9 16 $ node main.js 8 14 $ node main.js 7 20 $ node main.js 9 14 $ node main.js 9 19 |
。
1 2 3 | var arr=[]; arr[5]=0; alert("length="+arr.length); // gives 6 |
。
请人们不要放弃你的旧习惯。在分配内存一次然后处理该数组中的条目(如旧的)和在数组增长时多次分配内存(这不可避免地是系统在使用其他建议方法的情况下所做的)之间存在很大的速度差异。
当然,这些都不重要,除非你想用更大的数组做一些酷的事情。就这样。
由于目前JS中似乎没有设置数组初始容量的选项,所以我使用以下方法…
1 2 3 4 5 6 7 | var newArrayWithSize = function(size) { this.standard = this.standard||[]; for (var add = size-this.standard.length; add>0; add--) { this.standard.push(undefined);// or whatever } return this.standard.slice(0,size); } |
涉及到权衡:
小精灵
但是,如果它与你正在做的事情相符合,那就有可能得到回报。非正式时间安排
1 | for (var n=10000;n>0;n--) {var b = newArrayWithSize(10000);b[0]=0;} |
号
以相当快的速度(考虑到n=1000000,10000人大约需要50毫秒),并且
1 2 3 4 5 | for (var n=10000;n>0;n--) { var b = [];for (var add=10000;add>0;add--) { b.push(undefined); } } |
在超过一分钟的时间(在同一个Chrome控制台上,10000个约90秒,或者慢2000倍)。这不仅是分配,还包括10000次推送、for循环等。
这是另一个解决方案
1 2 3 | var arr = Array.apply( null, { length: 4 } ); arr; // [undefined, undefined, undefined, undefined] (in Chrome) arr.length; // 4 |
号
数组构造函数有一个不明确的语法,而jslint终究会伤害您的感情。
另外,示例代码被破坏,第二条
就你的选择而言,
假设数组的长度是常量。在javascript中,这是我们要做的:
埃多克斯1〔14〕
如上所述,使用
1 2 3 4 5 6 7 8 9 10 | function createArray(size, defaultVal) { var arr = new Array(size); if (arguments.length == 2) { // optional default value for (int i = 0; i < size; ++i) { arr[i] = defaultVal; } } return arr; } |
。
您可以使用
所以应该是
1 2 | var myArray = []; myArray.length = yourValue; |
不应使用
1 2 3 4 5 | var Array = function () {}; var x = new Array(4); alert(x.length); // undefined... |
。
其他一些代码可能会干扰数组变量。我知道有人会写这样的代码有点牵强,但是…
另外,正如FelixKing所说,接口有点不一致,可能导致一些非常难以跟踪的错误。
如果您想要一个长度为x、填充有未定义的数组(如
1 2 3 4 5 | var x = 4; var myArray = []; myArray[x - 1] = undefined; alert(myArray.length); // 4 |