2

I was trying to understand this code. Array(8).fill(0).map(Number.call, Number). The problem is that the behavior of this is very hard to understand because there is no way to see the implementation of number. If you try to .toString Number it will just say "native code". This is also true for using bind and call with the built in functions. How can I found out how this should behave?

peter duffy
  • 195
  • 9

1 Answers1

2

If you want to know how Number works in detail, take a look at its ECMAScript specs.

If you want to know how Number works in general, take a look at its MDN documentation.

Basically, all Number(value) does is to convert value into a number type. Nothing else.

I believe what you need to understand to understand this code is actually about Function.prototype.call instead of Number.

When we translate the above code into a less fancy one, we get something roughly like this (this is important for explanation below):

console.log(
  Array(8).fill(0).map(Function.prototype.call, Number)
);

Now, in .map, it receives 2 arguments:

  1. Callback, with 3 arguments: currentValue, currentIndex, originalArray.
  2. Custom this value

So what the above code does is passing Number.call as the callback, and Number as the custom this value.

If you understand .call method, you'll know it must receive at least 1 arguments:

  1. this value.
  2. ...Argument n

Knowing all these, we can now translate the code above to even less fancy one:

console.log(
  Array(8).fill(0).map(function(currentValue, currentIndex, originalArray){
    return this.call(currentValue, currentIndex);
  }, Number)
);

This can be translated to even less fancy one too:

console.log(
  // Making `currentValue` into `_` because its existence does not matter in this case
  Array(8).fill(0).map(function(_, currentIndex){
    return Number.call(_, currentIndex);
  })
);

Now, the final translation, which is the most understandable one:

console.log(
  Array(8).fill(0).map((_, i) => Number(i))
);
yqlim
  • 6,898
  • 3
  • 19
  • 43
  • So in `.map(Number.call, Number)`, the `Number` in `Number.call` can be replaced with any function name, and it will make no difference, since it's just to access `.call`? – GirkovArpa Sep 18 '20 at 02:39
  • 1
    @GirkovArpa that is correct. You can write `Array(8).fill(0).map(Boolean.call, Number)` and still get the same result – yqlim Sep 18 '20 at 03:05
  • @yqlim Why is Number.call just Function.prototype.call here? I'm guessing that when it evaluates `Number.cal(val,index,arraystate)` it firsts goes into the call code which does something like `this.(val,index,arraystate)` and because this is now `Number ` it goes into that call. What I really want to get to is that in JavaScript you can interact with a function not just based on its behavior(input output) but its implementation (how this is used), it just seems wrong then if I want to look for an implementation by using `toString` all i get is `[Native Code]`. --Also thanks for the anwser. – peter duffy Sep 19 '20 at 06:28
  • 1
    @peterduffy `Number.call` is `Function.prototype.call` because `Number instanceof Function` is true. The `.call` method is inherited from `Function` class. As for the implementation detail, different JS engines have different implementation but they all follow the [ECMAScript specs](https://www.ecma-international.org/ecma-262/) that I linked above, but if you're really keen, you can search for open source engine's code like [v8](https://github.com/v8/v8). – yqlim Sep 19 '20 at 08:08