Back in 2013 Gary Bernhardt published the following code snippet on Twitter:

['10','10','10','10','10'].map(parseInt);
// [10, NaN, 2, 3, 4]

At first glance, this is a classic WAT!? case in JavaScript. But once we understand how map() and parseInt actually work, we can make sense of this behavior.

parseInt()

parseInt() takes two parameters: the value to parse and an optional radix value (a value from 2 to 56 that represents the base in the mathematical system we want to use, with the default being set to 10).

const intValue = parseInt(string[, radix]);

Too often, only the first parameter is used though you should always specify the second parameter, too.

parseInt(100); // 100
parseInt(100, 10); // 100
parseInt(100, 2); // 4 -> converts 100 in base 2 to base 10

map()

map() to iterate over an array. Its callback function actually takes three arguments, though often only the first one is used (the other two are optional).

These arguments are:

  • currentValue - the current value processed in the array
  • index (optional) - the index of the current element being processed
  • array (optional) - the array map was called on
const arr = [1, 2, 3];
arr.map((num) => num + 1); // [2, 3, 4]

What’s Really Happening

Back to our original example. Here it is again.

['10','10','10','10','10'].map(parseInt);
// [10, NaN, 2, 3, 4]

For each iteration of map, parseInt() is being passed two parameters: the string and radix.

So this is what is happening:

parseInt('10', 0) // 10
parseInt('10', 1) // NaN
parseInt('10', 2) // 2
parseInt('10', 3) // 3
parseInt('10', 4) // 4

Now, why is parseInt('10', 0) equal 10 and not NaN! Because 0 is equivalent to falsy in JavaScript, so it defaults to base 10.

How to Do This in the Real World

What if you actually want to iterate over an array of strings with map() and change it to numbers? Use Number!

['10','10','10','10','10'].map(Number);
// [10, 10, 10, 10, 10]