From the Mozilla Developer Network:
[1,4,9].map(Math.sqrt)
will yield:
[1,2,3]
Why then does this:
['1','2','3'].map(parseInt)
yield this:
[1, NaN, NaN]
I have tested in Firefox 3.0.1 and Chrome 0.3 and just as a disclaimer, I know this is not cross-browser functionality (no IE).
I found out that the following will accomplish the desired effect. However, it still doesn’t explain the errant behavior of parseInt
.
['1','2','3'].map(function(i){return +i;}) // returns [1,2,3]
I'm going to wager that it's something funky going on with the parseInt's 2nd parameter, the radix. Why it is breaking with the use of Array.map and not when you call it directly, I do not know.
The callback function in
Array.map
has three parameters:From the same Mozilla page that you linked to:
So if you call a function
parseInt
which actually expects two arguments, the second argument will be the index of the element.In this case, you ended up calling
parseInt
with radix 0, 1 and 2 in turn. The first is the same as not supplying the parameter, so it defaulted based on the input (base 10, in this case). Base 1 is an impossible number base, and 3 is not a valid number in base 2:So in this case, you need the wrapper function:
or with ES2015+ syntax:
(In both cases, it's best to explicitly supply a radix to
parseInt
as shown, because otherwise it guesses the radix based on the input. In some older browsers, a leading 0 caused it to guess octal, which tended to be problematic. It will still guess hex if the string starts with0x
.)You can use arrow function ES2015/ES6 and just pass number to the parseInt. Default value for radix will be 10
Or you can explicitly specify radix for better readability of your code.
In example above radix explicitly set to 10
parseInt
IMHO should be avoided for this very reason. You can wrap it to make it more safe in these contexts like this:lodash/fp caps iteratee arguments to 1 by default to avoid these gotchas. Personally I have found these workarounds to create as many bugs as they avoid. Blacklisting
parseInt
in favor of a safer implementation is, I think, a better approach.another (working) quick fix :
map
is passing along a 2nd argument, which is (in many of the cases) messing upparseInt
's radix parameter.If you're using underscore you can do:
['10','1','100'].map(_.partial(parseInt, _, 10))
Or without underscore:
['10','1','100'].map(function(x) { return parseInt(x, 10); });