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);
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
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.
CodePudding user response:
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.