如何在javascript中初始化数组的长度?

时间:2011-01-31 14:29:08

标签: javascript arrays jslint

我在JavaScript中使用数组(包括w3schoolsdevguru)阅读的大多数教程都建议您可以通过将整数传递给Array构造函数来初始化具有一定长度的数组var test = new Array(4);语法。

在我的js文件中大量使用这种语法之后,我通过jsLint运行了一个文件,它吓坏了:

  

错误:第1行第22个问题:预期')'而是看到'4'   var test = new Array(4);
  第1行第23个问题:预期';'而是看到')'   var test = new Array(4);
  第1行第23个问题:预期标识符而不是')'。

阅读jsLint's explanation of its behavior后,看起来jsLint并不真正喜欢new Array()语法,而是在声明数组时更喜欢[]

所以我有几个问题。首先,为什么?我是否因使用new Array()语法而冒任何风险?是否存在我应该注意的浏览器不兼容性?第二,如果我切换到方括号语法,有没有办法声明一个数组并在一行上设置它的长度,或者我必须做这样的事情:

var test = [];
test.length = 4;

18 个答案:

答案 0 :(得分:429)

  • 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)

  • 如果你想用一定的价值进行初始化,这些都很有用...... Array.from('abcde')Array.from('x'.repeat(5))
    Array.from({length: 5}, (v, i) => i) // gives [0, 1, 2, 3, 4]

答案 1 :(得分:325)

  1. 为什么要初始化长度?从理论上讲,没有必要这样做。它甚至可能导致混淆行为,因为所有使用length来确定数组是否为空的测试都会报告该数组不为空。
    Some tests表示如果之后填充数组,设置大型数组的初始长度会更有效,但性能增益(如果有的话)似乎与浏览器不同浏览器。

  2. jsLint不喜欢new Array(),因为构造函数不明确。

    new Array(4);
    

    创建一个长度为的空数组 4.但是

    new Array('4');
    

    创建一个包含值 '4'的数组

  3. 关于你的评论:在JS中,你不需要初始化数组的长度。它动态增长。您可以将长度存储在某个变量中,例如

    var data = [];
    var length = 5; // user defined length
    
    for(var i = 0; i < length; i++) {
        data.push(createSomeObject());
    }
    

答案 2 :(得分:188)

使用ES2015 .fill(),您现在可以执行以下操作:

// `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)

Array.apply(0, new Array(n)).map(i => value)

更简洁

可以将0放入.fill()并运行不带参数,这将使数组填充undefined。 (但是,这将在Typescript中失败

答案 3 :(得分:53)

最短的:

[...Array(1000)]

答案 4 :(得分:33)

ES6引入Array.from,可让您从任何“类似数组” iterables 对象创建Array

Array.from({length: 10}, (x, i) => i);
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

在这种情况下,{length: 10}表示“类似数组”对象的最小定义:一个只定义了length属性的空对象。

Array.from允许第二个参数映射结果数组。

答案 5 :(得分:32)

[...Array(6)].map(x=>0);

// [0, 0, 0, 0, 0, 0]

Array(6).fill(0);

// [0, 0, 0, 0, 0, 0]

注意:您无法循环空广告位Array(4).forEach( (_,i) => {} )

Array(6).fill(null).map( (x,i) => i );

// [0, 1, 2, 3, 4, 5]

typescript safe

创建嵌套数组

直观地创建带有fill 2D 数组时,应创建新实例。但实际发生的事情是将相同的数组存储为参考。

var a = Array(3).fill([6]); 
// [[6], [6], [6]]

a[ 0 ].push( 9 );
// [[6,9], [6,9], [6,9]]

解决方案

var a = [...Array(3)].map(x=>[]); 

a[ 0 ].push( 4, 2 );
// [[4,2], [ ], [ ]]

所以3x2数组看起来像这样:

[...Array(3)].map(x=>Array(2).fill(0));

// [ [0,0] ,
//   [0,0] ,
//   [0,0] ]

答案 6 :(得分:25)

这会将length属性初始化为4:

var x = [,,,,];

答案 7 :(得分:16)

我很惊讶没有建议的功能性解决方案允许您将长度设置为一行。以下是基于UnderscoreJS:

var test = _.map(_.range(4), function () { return undefined; });
console.log(test.length);

由于上述原因,除非我想将数组初始化为特定值,否则我将避免这样做。值得注意的是,还有其他库可以实现范围,包括Lo-dash和Lazy,它们可能具有不同的性能特征。

答案 8 :(得分:8)

(作为评论可能更好,但是太长了)

因此,在阅读本文后,我很好奇预分配实际上是否更快,因为理论上它应该是。但是,这个博客提供了一些建议反对它http://www.html5rocks.com/en/tutorials/speed/v8/

所以仍然不确定,我把它做了测试。事实证明它似乎实际上更慢。

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); 

此代码在几次临时运行后产生以下结果:

$ 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

答案 9 :(得分:7)

var arr=[];
arr[5]=0;
alert("length="+arr.length); // gives 6

答案 10 :(得分:7)

请人们不要放弃你的旧习惯。 分配内存一次然后处理该阵列中的条目(从旧)开始,并在阵列增长时分配多次(这不可避免地是系统在其他建议的方法下做的事情)之间的速度差异很大

当然,除非你想用更大的数组做一些很酷的事情,否则这一切都不重要。然后呢。

看来JS目前似乎还没有选项来设置数组的初始容量,我使用以下内容......

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);
}

涉及权衡:

  • 此方法与第一次调用函数的时间相同,但后续调用的时间非常短(除非要求更大的数组)。
  • standard数组会永久保留与您要求的最大数组一样多的空间。

但如果它符合您所做的事情,那么可能会有回报。 非正式时间安排

for (var n=10000;n>0;n--) {var b = newArrayWithSize(10000);b[0]=0;}

速度非常快(10000左右,大约50毫秒,n = 1000000大约需要5秒),

for (var n=10000;n>0;n--) {
  var b = [];for (var add=10000;add>0;add--) {
    b.push(undefined);
  }
}

超过一分钟(相同的镀铬控制台上的10000大约90秒,或慢大约2000倍)。 这不仅仅是分配,而且还有10000次推送,for循环等等。

答案 11 :(得分:6)

这是另一种解决方案

var arr = Array.apply( null, { length: 4 } );
arr;  // [undefined, undefined, undefined, undefined] (in Chrome)
arr.length; // 4

apply()的第一个参数是一个这个对象绑定,我们在这里并不关心,因此我们将其设置为null

Array.apply(..)正在调用Array(..)函数并将{ length: 3 }对象值作为其参数展开。

答案 12 :(得分:3)

数组构造函数有一个ambiguous syntax,而JSLint毕竟只会伤害你的感情。

此外,您的示例代码已损坏,第二个var语句将引发SyntaxError。您正在设置数组length的属性test,因此不需要其他var

就你的选择而言,array.length是唯一的“干净”选择。问题是,为什么你需要首先设置尺寸?尝试重构您的代码以摆脱该依赖。

答案 13 :(得分:2)

假定数组的长度是恒定的。在Javascript中,这是我们要做的:

const intialArray = new Array(specify the value);

答案 14 :(得分:1)

如上所述,使用new Array(size)有点危险。而不是直接使用它,将其放在“数组创建器函数”中。您可以轻松确保此功能没有错误,并避免直接调用new Array(size)的危险。此外,您可以为其提供可选的默认初始值。这个createArray函数就是这样做的:

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;
}

答案 15 :(得分:0)

在大多数答案中,建议使用fill数组,否则“您无法对其进行迭代” ,但这不是事实。您可以迭代一个空数组,而不能使用forEach进行迭代。 While循环,for循环和for i循环工作正常。

const count = Array(5);

不起作用。

console.log('---for each loop:---');
count.forEach((empty, index) => {
    console.log(`counting ${index}`);
});

这些作品:

console.log('---for of loop:---');
for (let [index, empty] of count.entries()) {
  console.log(`counting for of loop ${index}`);
}

console.log('---for i loop:---');
for (let i = 0, il = count.length; i < il; ++i) {
  console.log(`counting for i loop ${i}`);
}

console.log('---while loop:---');
let index = 0;
while (index < count.length) { 
  console.log(`counting while loop ${index}`); 
  index++; 
}

通过上述示例检查 this fiddle

角度*ngFor也可以与空数组配合使用:

<li *ngFor="let empty of count; let i = index" [ngClass]="
  <span>Counting with *ngFor {{i}}</span>
</li>

答案 16 :(得分:-1)

您可以使用array.length = youValue

设置数组长度

所以它会是

var myArray = [];
myArray.length = yourValue;

答案 17 :(得分:-1)

此代码演示了您不应使用new Array的原因:

var Array = function () {};

var x = new Array(4);

alert(x.length);  // undefined...

其他一些代码可以搞乱Array变量。我知道任何人都会写这样的代码有点牵强,但仍然......

另外,正如Felix King所说,界面有点不一致,可能会导致一些非常难以追踪的错误。

如果你想要一个长度为x的数组,填充未定义(如new Array(x)那样),你可以这样做:

var x = 4;
var myArray = [];
myArray[x - 1] = undefined;

alert(myArray.length); // 4