Why does parseInt yield NaN with Array#map?

05/10/2020 15:00:01

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]

Verified Answer (476 Votes)

11/04/2008 22:02:14

The callback function in Array.map has three parameters:

From the same Mozilla page that you linked to:

callback is invoked with three arguments: the value of the element, the index of the element, and the Array object being traversed."

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:

parseInt('1', 0); // OK - gives 1
parseInt('2', 1); // FAIL - 1 isn't a legal radix
parseInt('3', 2); // FAIL - 3 isn't legal in base 2 

So in this case, you need the wrapper function:

['1','2','3'].map(function(num) { return parseInt(num, 10); });

or with ES2015+ syntax:

['1','2','3'].map(num => parseInt(num, 10));

(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 with 0x.)

476

Answer #2 (25 Votes)

11/11/2014 04:54:02

map is passing along a 2nd argument, which is (in many of the cases) messing up parseInt'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); });

25

Answer #3 (18 Votes)

11/12/2016 18:45:54

You could solve this problem using Number as iteratee function:

var a = ['0', '1', '2', '10', '15', '57'].map(Number);

console.log(a);

Without the new operator, Number can be used to perform type conversion. However, it differs from parseInt: it doesn't parse the string and returns NaN if the number cannot be converted. For instance:

console.log(parseInt("19asdf"));
console.log(Number("19asf"));

18
3
Hack Hex uses Stack Exchance API by the Stack Exchange Inc. to scrape questions/answers under Creative Commons license.