Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript map array with 'fromCharCode' (character length)

Tags:

javascript

The following is from an interactive session in the Chrome console:

myarray
//-> [67, 65, 84]

String.fromCharCode(67)
//-> "C"

String.fromCharCode(67).length
//-> 1

String.fromCharCode(myarray[0])
//-> "C"

String.fromCharCode(myarray[0]).length
//-> 1

myarray.map(String.fromCharCode)
//-> ["C", "A", "T"]

myarray.map(String.fromCharCode)[0]
//-> "C"

myarray.map(String.fromCharCode)[0].length
//-> 3

Can anyone explain why the last operation returns 3?

like image 348
David Wallis Avatar asked Apr 06 '11 13:04

David Wallis


People also ask

What does string fromCharCode do in JavaScript?

In JavaScript, fromCharCode() is a string method that is used to create a string from a sequence of Unicode values. Because the fromCharCode() method is a static method of the String constructor, it must be invoked through the String constructor object rather than through the particular instance of the String class.

Does map mutate array?

map does not mutate the array on which it is called (although callbackFn , if invoked, may do so). The range of elements processed by map is set before the first invocation of callbackFn .

What is map () in JavaScript?

Definition and Usage. map() creates a new array from calling a function for every array element. map() calls a function once for each element in an array. map() does not execute the function for empty elements. map() does not change the original array.

Does map work on arrays?

The map() method in JavaScript creates an array by calling a specific function on each element present in the parent array. It is a non-mutating method. Generally map() method is used to iterate over an array and calling function on every element of array.


2 Answers

Very interesting question.

And the answer is: The reason you're getting 3 at the end is that fromCharCode returns a string with as many characters as there are arguments in the call to it, and map calls the callback function with three arguments: The value of the element, the index of the element, and the object being traversed. Thus, a string with three characters, but not three readily-displayed characters. Tricky.

Specifically, we get "C" for the first argument; character 0 for the second argument (since we're looking at [0]; it would be 1 for [1], etc.), and a character based on coercing the array into a number (using whatever rules fromCharCode uses for that; Šime Vidas says below that it'll do ToUInt16 on it, which will result in 0).

So, for instance:

> String.fromCharCode(67, 0, [67, 65, 84]).length
3

...just as with the 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 ensure we only pass it the one argument at a time, we don't see that unexpected effect, so while using it directly gives us a result I think most of us wouldn't 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 easily-understood 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
like image 179
T.J. Crowder Avatar answered Nov 21 '22 22:11

T.J. Crowder


I can't expand much on T.J. Crowder's great answer, but I can provide a workaround for this specific problem.

Rather than

myarray.map(String.fromCharCode);

Use

String.fromCharCode.apply(String, myarray).split("");

Aside from the benefit of returning the expected result, this also works without relying on the ECMAScript 5th Edition method, Array.prototype.map, thus making it more compatible.

like image 23
Andy E Avatar answered Nov 22 '22 00:11

Andy E