Jonathan Kuhl

Posted on

# The Problem

Consider the following problem I came across on r/learnjavascript: Why does `[1,3,11].map(parseInt)` result in `[1, NaN, 3]`?

It is common for new developers to be unaware of how map works and how it feeds parameters to the function it is provided. We're all aware that the first parameter it gives is the element in the array we're currently iterating over.

For example: `[1,3,11].map(element => console.log(element))` gives us an output that lists 1, 3, 11.

But the fact is, map actually feeds three parameters to the given function. Map provides the current element being iterated over, the current index we're at, and the array being iterated over.

``````[1,3,11].map((element, index, array) => //... )
``````

We can see this by changing our console.log by referring to it directly rather than wrapping it in an anonymous function:

``````[1,3,11].map(console.log)
1 0 [ 1, 3, 11 ]
3 1 [ 1, 3, 11 ]
11 2 [ 1, 3, 11 ]
``````

This is pasted directly from the node REPL. You can see here, we get on each line, the element, the index, and the array.

So back to the original problem, why do we get `[1, NaN, 3]`?

Because these three arguments are being passed into `parseInt`. I believe that many new developers forget that `parseInt` actually takes two arguments, more than they would forget that `map` provides three arguments. `parseInt` takes a number and the radix. The radix tells `parseInt` which number system we're using. 0 is decimal, 2 is binary, 3 is trinary, 8 is octal, 16 is hex, and so on and so forth.

`parseInt(11, 3)` outputs `2` because that's it's trinary equivalent.

So on each pass in `map`, `parseInt` looks like this:

``````parseInt(1, 0);
parseInt(3, 1);
parseInt(11, 2);
``````

The array argument is ignored because `parseInt` only takes two arguments. The number provided becomes the element from the array and the radix comes from the index.

On the first pass, we're converting 1 to decimal, which is of course, 1. A radix of 0 and 10 are decimal, so nothing changes with decimal numbers. On the second pass, we get `NaN` because the value `1` is invalid for a radix. And on the third pass, we're converting `11` to `2`. `11` in binary is of course, `3`. We have a 1 in the 2^1 position and a 1 in the 2^0 position, 2^1 + 2^0 = 2 + 1 = 3.

In short, the reason we get unexpected values, is because `map` provides more arguments to the `parseInt` function than we desired.

# How do we fix this?

The solution is very simple, we don't directly pass a reference to a function like `parseInt` to `map`. Instead, it's best to wrap it in an anonymous function first:

``````[1, 3, 11].map((element, index, array) => parseInt(element) );
``````

Of course you can omit the `index` or `array` parameters if you aren't using them, I left them in for illustration

Then you can pass your arguments to the function as needed.

Now this is only necessary for functions that take, or potentially take, multiple arguments. If you want to map with a function that only takes one argument, feel free to pass it the reference directly.

``````const square = x => x * x;
[1,2,3].map(square);
//  [1, 4, 9]
``````

Just be careful to be sure whatever you pass into `map`, and this goes for `foreach` and many of the other array methods as well, only takes one argument.

You can read more about how `parseInt` works on the Mozilla Developer Network here.

Happy coding.