How to initialize an array's length in JavaScript?

Solution 1:

  • 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 2:

  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 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:

[...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 i.e. Array(4).forEach(() => …)


OR

( typescript safe )

Array(6).fill(null).map((_, i) => i);
// [0, 1, 2, 3, 4, 5]

OR

Classic method using a function ( works in any browser )

function NewArray(size) {
    var x = [];
    for (var i = 0; i < size; ++i) {
        x[i] = i;
    }
    return x;
}

var a = NewArray(10);
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Creating nested arrays

When creating a 2D array with the fill intuitively should create new instances. But what actually going to happen 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 3x2 Array will look something like this:

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

N-dimensional array

function NArray(...dimensions) {
    var index = 0;
    function NArrayRec(dims) {
        var first = dims[0], next = dims.slice().splice(1); 
        if(dims.length > 1) 
            return Array(dims[0]).fill(null).map((x, i) => NArrayRec(next ));
        return Array(dims[0]).fill(null).map((x, i) => (index++));
    }
    return NArrayRec(dimensions);
}

var arr = NArray(3, 2, 4);
// [   [  [ 0,  1,  2,  3 ] , [  4,  5,  6,  7]  ],
//     [  [ 8,  9,  10, 11] , [ 12, 13, 14, 15]  ],
//     [  [ 16, 17, 18, 19] , [ 20, 21, 22, 23]  ]   ]

Initialize a chessboard

var Chessboard = [...Array(8)].map((x, j) => {
    return Array(8).fill(null).map((y, i) => {
        return `${String.fromCharCode(65 + i)}${8 - j}`;
    });
});

// [ [A8, B8, C8, D8, E8, F8, G8, H8],
//   [A7, B7, C7, D7, E7, F7, G7, H7],
//   [A6, B6, C6, D6, E6, F6, G6, H6],
//   [A5, B5, C5, D5, E5, F5, G5, H5],
//   [A4, B4, C4, D4, E4, F4, G4, H4],
//   [A3, B3, C3, D3, E3, F3, G3, H3],
//   [A2, B2, C2, D2, E2, F2, G2, H2],
//   [A1, B1, C1, D1, E1, F1, G1, H1] ]

Math filled values

handy little method overload when working with math


function NewArray( size , method, linear )
{
    method = method || ( i => i ); 
    linear = linear || false;
    var x = [];
    for( var i = 0; i < size; ++i )
        x[ i ] = method( linear ? i / (size-1) : i );
    return x;
}

NewArray( 4 ); 
// [ 0, 1, 2, 3 ]

NewArray( 4, Math.sin ); 
// [ 0, 0.841, 0.909, 0.141 ]

NewArray( 4, Math.sin, true );
// [ 0, 0.327, 0.618, 0.841 ]

var pow2 = ( x ) => x * x;

NewArray( 4, pow2 ); 
// [ 0, 1, 4, 9 ]

NewArray( 4, pow2, true ); 
// [ 0, 0.111, 0.444, 1 ]

Solution 5:

The shortest:

let arr = [...Array(10)];
console.log(arr);