0

The following code:

let resultsArray = Array.apply(null, Array(10)).map(Number.prototype.valueOf,0);

creates the following array

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

Why does map() need Number.prototype.valueOf just to push the number 0 in to each position of this array. Is there a different (more efficient) way to achieve this result, or is this the best way?

Jeremy Iglehart
  • 4,281
  • 5
  • 25
  • 38

3 Answers3

3

If you read the map documentation you can read this:

The map() method creates a new array with the results of calling a provided function on every element in this array.

So you need to use the function Number.prototype.valueOf in first parameter and a Number object in second optional parameter to fill the new array. The Number object is used as the this of the first parameter.

You can also write this for the same result:

let resultsArray = Array.apply(null, Array(10)).map(function(){return 0;});

But if you juste want to fill an array with a value, I think you may use the Array.prototype.fill method.

The fill() method fills all the elements of an array from a start index to an end index with a static value.

let resultsArray = (new Array(10)).fill(0);

Performance test:

var start, stop, array;
var iteration = 100000;


// Map
start = Date.now();
array = Array.apply(null, Array(iteration)).map(Number.prototype.valueOf,0);
stop = Date.now();
console.log("Map executed in "+(stop-start)+"ms");

// Map simple array
start = Date.now();
array = (new Array(iteration)).map(Number.prototype.valueOf,0);
stop = Date.now();
console.log("Map simple array executed in "+(stop-start)+"ms");

// Map simple function
start = Date.now();
array = (new Array(iteration)).map(function(){return 0;});
stop = Date.now();
console.log("Map simple function executed in "+(stop-start)+"ms");

// Array.from - ES6 from @Zohaib ijaz
start = Date.now();
array = Array.from(new Array(iteration), () => 0)
stop = Date.now();
console.log("Array.from - ES6 from @Zohaib ijaz executed in "+(stop-start)+"ms");

// Array.from - Non-ES6 from @Zohaib ijaz
start = Date.now();
array = Array.from(new Array(iteration), function(){return 0;})
stop = Date.now();
console.log("Array.from - Non-ES6 from @Zohaib ijaz executed in "+(stop-start)+"ms");

// repeat-split-map by @nicael
start = Date.now();
array = '0'.repeat(iteration).split('').map(Number);
stop = Date.now();
console.log("repeat-split-map by @nicael executed in "+(stop-start)+"ms");

// Fill
start = Date.now();
array = (new Array(iteration)).fill(0);
stop = Date.now();
console.log("Fill executed in "+(stop-start)+"ms");
Jeremy Iglehart
  • 4,281
  • 5
  • 25
  • 38
Techniv
  • 1,967
  • 15
  • 22
  • I really like this solution it is shorter and way easier to read than `resultsArray = Array.apply(null, Array(10)).map(Number.prototype.valueOf,10);` I wonder if it's more efficient too? – Jeremy Iglehart Jun 17 '16 at 20:10
  • I don't know if it realy more efficient. I think beceause you use only one array insted of two. But it's more appropriate to fill an array. The map method is used to produce an array from an other by a mapping function. Filling an array with map is a hack. – Techniv Jun 18 '16 at 17:56
  • I have edit my post with some tests. Fill is definitively more efficient. – Techniv Jun 18 '16 at 18:29
  • 1
    [@Techniv](http://stackoverflow.com/users/1613723/techniv) - Awesome work! Thank you for improving your answer. Not only did you provide a good answer but your benchmark snippet proves that fill is by far the best, running in my browser I'm getting between 4ms, 2ms and even 1ms - as compared to over 100ms for other possible ways. - P.S. I added the other suggestion here by [@nicael](http://stackoverflow.com/users/2963652/nicael) to see how his suggestion stands up to yours to see which is faster. – Jeremy Iglehart Jun 18 '16 at 22:11
  • 1
    I added the suggection from @Zohaib ijaz also to see how it would perform against the others. – Jeremy Iglehart Jun 18 '16 at 22:26
0

In your code, 0 is passed to Number.prototype.valueOf which just returns the primitive (0).

Which is essentially the same thing as

Number.prototype.valueOf.call(0)

If your code was:

let resultsArray = Array.apply(null, Array(10)).map(Number.prototype.valueOf,10);

The map() function would essentially be calling Number.prototype.valueOf like this:

Number.prototype.valueOf.call(10)

Here's the documentation - which provides a nice Polyfill that you can read and see exactly what map() is doing.


Strings would look like this:

Array.apply(null, Array(10)).map(String.prototype.valueOf,"10")

Which would output:

["10", "10", "10", "10", "10", "10", "10", "10", "10", "10"]

But surely you can do it in a more tricky way ;)

var resultsArray = '0'.repeat(10).split('').map(Number);
console.log(resultsArray);

And in case it's not necessary to get the numbers (but strings), it's even shorter:

var resultsArray = '0'.repeat(10).split('');
console.log(resultsArray);
nicael
  • 18,550
  • 13
  • 57
  • 90
  • @Jeremy I haven't thought of it yet, we could run and check the timing. – nicael Jun 17 '16 at 19:10
  • @Jeremy I've tried to loop 100,000 times creature of either of variables, both take about 150 ms. – nicael Jun 17 '16 at 19:15
  • @Jeremy Thanks for this :)) sorry if it was unclear! – nicael Jun 17 '16 at 19:38
  • [@nicael](http://stackoverflow.com/users/2963652/nicael) Thanks for your answer! - and the edit was just because this is how it made sense to me. Your answer was correct and clear. I thought I would just expand it a little for other people coming by. – Jeremy Iglehart Jun 17 '16 at 19:45
  • [@nicael](http://stackoverflow.com/users/2963652/nicael) Interesting trick. I still like this other way, it seams more graceful once you understand what map is doing - I like the way the code reads. – Jeremy Iglehart Jun 17 '16 at 19:46
  • @Jeremy Ah, sorry, misunderstood. – nicael Jun 17 '16 at 19:55
  • @Jeremy Removed the header styling, since it looked awkward. – nicael Jun 17 '16 at 19:58
  • [@nicael](http://stackoverflow.com/users/2963652/nicael) you didn't misunderstand anything! Thank you for your code alternative :) And no worries, it's your answer - style how you'd like. – Jeremy Iglehart Jun 17 '16 at 20:07
  • @Jeremy I've removed that fact which I have misunderstood, it's unrelated to previous comments :) – nicael Jun 17 '16 at 20:08
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/114986/discussion-between-jeremy-iglehart-and-nicael). – Jeremy Iglehart Jun 18 '16 at 01:20
0

There is another solution

Array.from(new Array(10), () => 0)

Ad if your browser does not support ES6, then

Array.from(new Array(10), function(){return 0;})
Zohaib Ijaz
  • 21,926
  • 7
  • 38
  • 60