1

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.

Satish Chandra Gupta
  • 2,970
  • 1
  • 22
  • 22
  • 1
    You don’t understand it despite knowing all the methods? The MDN documentation describes how each of these methods works, in particular which arguments they accept, and what they all mean. So you _don’t_ understand the methods? Which ones do you not understand? The code itself is a needlessly confusing way to write the more idiomatic `Array.from({ length: 10 }, (_, index) => index)`. – Sebastian Simon Nov 07 '21 at 11:41
  • Sebastian, if you understand it well then explain the working part `.map(Number.call, Number)` with code before it. – Satish Chandra Gupta Nov 07 '21 at 11:45
  • I mean… it’s all explained in the [documentation](//developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/map). `map` accepts two arguments. The first one is a function that is called with three arguments. [`.call`](//developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Function/call) accepts any number of arguments: the first one is the `this` value, the rest are the actual function arguments. The second `map` argument provides the necessary `this` context for `Number.call`. See [How does the "this" keyword work?](/q/3127429/4642212). – Sebastian Simon Nov 07 '21 at 11:50

1 Answers1

3

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.

Nick Parsons
  • 45,728
  • 6
  • 46
  • 64