Search code examples
javascriptarraysjavascript-objects

Break down 1 liner javascript


I came across a JavaScript code that creates an array and fills it with numbers from 0-9.

The code is:

var arr = Array.apply(null, {length: 10}).map(Number.call, Number);
console.log(arr);

The code above creates an array and pushes numbers from 0-9 in it. I do not understand how it is working. I know all the methods that are used in this like apply, map, and call but still don't understand how it is working.

Can anyone please explain the working of code by breaking it into chunks? Like how step-by-step code is being executed and how it is resulting in an array that has numbers from 0-9.


Solution

  • Firstly, your code creates an array of 10 elements, all of which being undefined using the below code:

    Array.apply(null, {length: 10})
    

    The above is like writing:

    Array(undefined, undefined, undefined, undefined, ... 6 more times ...)
    

    This works because the object {length: 10} is array-like as it has a length property. Usually the second argument to .apply() is an array of arguments that you want to call the function with. However, as you're passing an object in this case, JS takes the length property and calls the Array() function with 10 undefined arguments, as the keys of the {length: 10} object don't define values for properties 0 to 9.

    Next, the array of 10 undefined values are mapped. When using .map(), the first argument is the mapping function and the second argument to the .map() method is the this argument, which indicates what this should refer to inside of the first mapping function. One way of looking at your map method is to rerwrite it like so:

    .map((element, index, array) => Number.call(element, index, array))
    

    The .map() method will iterate through all of your 10 undefined elements, and for each element your callback will be invoked with the index of that element. When using Number.call(), the this for the Number() function call is set to undefined (ie: element). This doesn't impact how the call to Number() behaves as it doesn't rely on any particular value for its execution. As a result, the above Number.call method is the same as using Number(index, array), where array is discarded, so it's simply performing Number(index).

    The second argument to the .map() method is to define the this binding for the first mapping function that you pass into the .map() method. When you pass Number.call as the mapping function, you're passing a reference to the call method defined on Function.prototype.call. The call method only knows what function it should invoke based on its this value defined when calling the .call() method. As you're only passing the .map() method a reference to the call() function, and not invoking it with (), the this is lost, and so you need to explicitly define what the this value is. That can be done by passing through Number as the second argument to your map method call.