4

I want to generate an empty array of a given length and the populate it with some numbers. One way to generate an array with four sequential numerical elements is :

var x = Array.apply(null, {length: 4}).map(function(item, index){return index;})

But when I saw Array.apply(null, {length: 4}) I thought I could instead replace it with new Array(4) but that is not the case. Doing a quick test yields the following:

>> console.log((new Array(4)))
<< [ <4 empty items> ]

>> console.log(Array.apply(null, {length: 4}))
<< [ undefined, undefined, undefined, undefined ]

Which means I can .map the latter but not the former.

What is the difference then between new Array and Array.apply(null, {}) which I thought were both creating an array object with given length?

2
  • this seems very inefficient as it creates a new array. Commented Jun 21, 2018 at 17:39
  • 1
    What's the question? The results of the operations should make it obvious what the differences are. Are you asking for references to the specifications? Commented Jun 21, 2018 at 17:42

3 Answers 3

7

apply takes a context as the first parameter and an arraylike list of arguments as a second. Then it calls the function (Array) with the iterable as arguments.

Array.apply(null, [1, 2])
// Same as
Array(1, 2)
// Or
[1, 2]

Now if you pass an object as an arraylike, it will still iterate it like this:

function apply(context, args) {
  for(var i = 0; i < args.length; i++) { 
    /*...*/ args[i];
  }
}

So if you pass { length: 4 } it will iterate four times and take undefined as an argument, so it results in something like:

Array.apply(null, { length: 4 })
// Same as
Array(undefined, undefined, undefined)

Therefore the arrays slots are not empty, but they are undefined, and as map only skips empty slots it will go over every entry of the second array.

By the way, the same can be achieved a bit more readable:

Array.from({length: 4 }, (_, i) => i)
// [0, 1, 2, 3]
Sign up to request clarification or add additional context in comments.

Comments

3

The answer requires a bit of drilling down into the mechanics of Array objects.

new Array(4) creates an array with length 4 but no items (Sparse Array)

Array.apply(null, {length: 4}) creates an array with 4 undefined elements.

The second one uses a few tricks:

  1. apply calls a function with given context and arguments provided in an array.

  2. Array, when called directly as a function creates an array from the elements it got as arguments, e.g:

    \> Array(1,2,3) [ 1, 2, 3 ] \> Array(...[1,2,3]) [ 1, 2, 3 ] \> Array(...new Array(4)) [ undefined, undefined, undefined, undefined ]

So why is Array.apply(null, {length: 4}) equivalent to Array.apply(null, new Array(4)?

apply parses the arguments array by looking at the length and then taking the relevant arguments. {length: 4}.length is 4, so it takes

{length:4}[0]
{length:4}[1]
{length:4}[2]
{length:4}[3]

which are all undefined.

Comments

0

The difference is that new Array(4) does not initialize the slots in the array. It only sets the length property of the array. Where as Array.apply(null, {length: 4}) initializes each slot to undefined.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.