95

Using the Chrome Console, this is my input and output:

[0].map(Array);

[[0, 0, [0]]]; // output

What is happening here?

EDIT

The reason this makes me curious is because something like

[0].map(String);

Will return

["0"];

And not

["0", "0", "String"]
Jacksonkr
  • 31,583
  • 39
  • 180
  • 284
  • 34
    I assume because he always needs some Javascript WTFs in order to feel happy – npst Sep 15 '17 at 12:04
  • 12
    Oh, it's just a less wtf-y variant of `['10', '10', '10'].map(parseInt)` – gronostaj Sep 15 '17 at 17:26
  • 2
    Another strange `.map()` behavior: https://stackoverflow.com/questions/14528397/strange-behavior-for-map-parseint In general, you have to be careful when using `.map()` with functions that take more than one argument. – Barmar Sep 16 '17 at 05:54
  • 2
    Just do `[0].map(console.log)` – Bergi Sep 16 '17 at 20:03
  • @Bergi `0 0 > [0]` \n [undefined]` #chrome60.0.3112.113x64 #osx10.12.6 – Jacksonkr Sep 16 '17 at 23:08
  • @npst: Ahah. I just landed on this question because it was a "Hot Network Questions". I don't actively look for Javascript WTFs. – Eric Duminil Sep 17 '17 at 10:40
  • @EricDuminil npst's comment was directed toward another SOFer who was commenting about Javascript's occasional WTF behavior. The original commenter removed his comment and npst's stayed. What cracks me up is that npst still received 24 upvotes even out of context. – Jacksonkr Sep 19 '17 at 23:55
  • 1
    @Jacksonkr: Thanks for the answer. I think it went like this : I wrote a comment, explaining that seeing JS WTFs makes me happy I don't have to use the language often. Someone asked why I would look at JS questions if I don't like the language. npst answered, and the first two comments got deleted. It's funny his comment still gets upvoted, yes. – Eric Duminil Sep 20 '17 at 06:52

4 Answers4

123

The .map() function is calling the Array() function with three arguments, the value of the array element which is 0, the index of that element, also 0, and a reference to the whole array.

So it's like doing this:

var a = [0];
var index = 0
Array(a[index], index, a);   // create array with three elements

The array returned by Array() then becomes the first element of the array that .map() creates, hence the extra level of nesting in your [[0, 0, [0]]] result.

EDIT regarding your edit: when you say [0].map(String); that results in String() being called with the same three arguments like String(a[index], index, a), but the String() function ignores all but the first argument, whereas Array() uses all supplied arguments.

nnnnnn
  • 147,572
  • 30
  • 200
  • 241
38

Firstly, Array could be used as a function to create arrays:

var arr = Array(1, 2, "Hello");

console.log(arr); // [1, 2, "Hello"]

Secondly, map passes three parameters to its callback: the element, its index from the array and the array itself.

So, since your array contains one element, the line:

[0].map(Array);

is equivalent to:

[Array(0, 0, [0])];     // the element 0 in the original array will be mapped into Array(0, 0, [0])
user229044
  • 232,980
  • 40
  • 330
  • 338
ibrahim mahrir
  • 31,174
  • 5
  • 48
  • 73
6

After you updated question. Other answers provide you info about map

To answer why array and string differ look to constructors

String constructor accept 1 parameter String(thing) while array new Array(element0, element1[, ...[, elementN]])

Vova Bilyachat
  • 18,765
  • 4
  • 55
  • 80
4

This call

[0].map(Array);

gives you the same result as if you wrote something like this:

[0].map(function (value, index, array) {
    return Array(value, index, array);
})

Map function is calling Array function with three parameters: value of element, index of element and whole array. This call to Array returns you array with 3 elements: value (number 0), index (number 0), whole array ([0]).

And this new array is wrapped in the original Array, because you maped original element (number 0) to new element (array of 3 elements)

Note: You might be used to using only the first parameter like in

array.map(function (a) { return a * a; });

or using just two to get also index

array.map(function (item, index) { return "index=" + index + ", value=" + item; });

But you need to remember that map still provides 3 parameters you just ignore them in your callback function. That's also the reason why code like:

[0].map(String);

returns

["0"]

It's because String function care only about the first parameter and ignores other passed parameters. If you call

String(11, "Some", "other", "ignored", "parameters")

you will still get

"11"
Mariusz Pawelski
  • 25,983
  • 11
  • 67
  • 80