A Trick With Map
Tags: javascript
Published: 2019-06-14 04:09:27

---
title: A Trick With Map
published: True
description: Array.prototype.map is very powerful, but comes with one little trip
tags: javascript
---

# The Problem

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

# The Answer

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.

```javascript
[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:

```javascript
[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:

```javascript
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:

```javascript
[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.

```javascript
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](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt).

Happy coding.