How to initialize an array’s length in javascript?

How to initialize an array’s length in javascript?

Most of the tutorials that I’ve read on arrays in JavaScript (including w3schools and devguru) suggest that you can initialize an array with a certain length by passing an integer to the Array constructor using the var test = new Array(4); syntax.
After using this syntax liberally in my js files, I ran one of the files through jsLint, and it freaked out:

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 ‘)’.

After reading through jsLint’s explanation of its behavior, it looks like jsLint doesn’t really like the new Array() syntax, and instead prefers [] when declaring arrays.
So I have a couple questions. First, why? Am I running any risk by using the new Array() syntax instead? Are there browser incompatibilities that I should be aware of? And second, if I switch to the square bracket syntax, is there any way to declare an array and set its length all on one line, or do I have to do something like this:
var test = [];
test.length = 4;

Solutions/Answers:

Solution 1:

  1. Why do you want to initialize the length? Theoretically there is no need for this. It can even result in confusing behavior, because all tests that use the length to find out whether an array is empty or not will report that the array is not empty.
    Some tests show that setting the initial length of large arrays can be more efficient if the array is filled afterwards, but the performance gain (if any) seem to differ from browser to browser.

  2. jsLint does not like new Array() because the constructer is ambiguous.

    new Array(4);
    

    creates an empty array of length 4. But

    new Array('4');
    

    creates an array containing the value '4'.

Regarding your comment: In JS you don’t need to initialize the length of the array. It grows dynamically. You can just store the length in some variable, e.g.

var data = [];
var length = 5; // user defined length

for(var i = 0; i < length; i++) {
    data.push(createSomeObject());
}

Solution 2:

  • Array(5) gives you an array with length 5 but no values, hence you can’t iterate over it.

  • Array.apply(null, Array(5)).map(function () {}) gives you an array with length 5 and undefined as values, now it can be iterated over.

  • Array.apply(null, Array(5)).map(function (x, i) { return i; }) gives you an array with length 5 and values 0,1,2,3,4.

  • Array(5).forEach(alert) does nothing, Array.apply(null, Array(5)).forEach(alert) gives you 5 alerts

  • ES6 gives us Array.from so now you can also use Array.from(Array(5)).forEach(alert)

  • If you want to initialize with a certain value, these are good to knows…
    Array.from('abcde'), Array.from('x'.repeat(5))
    or Array.from({length: 5}, (v, i) => i) // gives [0, 1, 2, 3, 4]

Solution 3:

With ES2015 .fill() you can now simply do:

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

Which is a lot more concise than Array.apply(0, new Array(n)).map(i => value)

It is possible to drop the 0 in .fill() and run without arguments, which will fill the array with undefined. (However, this will fail in Typescript)

Solution 4:

The shortest:

[...Array(1000)]

Solution 5:

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

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

OR

Array(6).fill(0);

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

Note: you can’t loop empty slots Array(4).forEach( (_,i) => {} )

OR

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

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

( typescript safe )


Creating nested arrays

When creating a 2D array with the fill intuitively should create new instances. But what actually going to happened is the same array will be stored as a reference.

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

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

Solution

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

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

So a 3×2 Array will look something like this:

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

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

Solution 6:

ES6 introduces Array.from which lets you create an Array from any “array-like” or iterables objects:

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

In this case {length: 10} represents the minimal definition of an “array-like” object: an empty object with just a length property defined.

Array.from allows for a second argument to map over the resulting array.