Very interesting question.
And the answer: the reason you get 3 at the end is because fromCharCode returns a string with as many characters as arguments in its call, and map calls a callback function with three arguments: element value, element index, and passed an object. Thus, a string with three characters, but not three easily displayed characters. Tricky.
In particular, we get "C" for the first argument; the character is 0 for the second argument (since we look at [0] , it will be 1 for [1] , etc.), and the character based on forcing the array to a number (using any fromCharCode rules for which Ε ime Vidas says below that it will have ToUInt16 , which will result in 0 ).
So for example:
> String.fromCharCode(67, 0, [67, 65, 84]).length 3
... just like with a call from map .
For clarity:
> String.fromCharCode(67, 0, [67, 65, 84]).length 3 > String.fromCharCode(67, 0, null).length 3 > String.fromCharCode(67, 0, 0, 0, 0, 0, 0).length 7
If we guarantee that we pass only one argument at a time, we do not see this unexpected effect, so when it is used it gives us the result, I think most of us did not expect:
> [67, 65, 84].map(String.fromCharCode) ["C", "A", "T"] > [67, 65, 84].map(String.fromCharCode)[0] "C" > [67, 65, 84].map(String.fromCharCode)[0].length 3
... this gives us a more understandable result:
> [67, 65, 84].map(function(value) { return String.fromCharCode(value); }) ["C", "A", "T"] > [67, 65, 84].map(function(value) { return String.fromCharCode(value); })[0] "C" > [67, 65, 84].map(function(value) { return String.fromCharCode(value); })[0].length 1