The Trap of Using map with parseInt in JavaScript

This article analyzes in detail why ["1","2","3"].map(parseInt) returns [1, NaN, NaN] in JavaScript, revealing this common JavaScript trap by examining how map and parseInt methods work.

In JavaScript, there’s a classic question:

["1","2","3"].map(parseInt)

What is the return value of this code? Many people might think it’s [1, 2, 3], but it’s actually [1, NaN, NaN]. Why is that? Let’s analyze it together.

How the map Method Works

First, we need to understand how the map method works. The map method calls the provided function once for each element in the array and creates a new array with the return values of the function.

The callback function for the map method accepts three parameters:

  1. currentValue: The current element being processed
  2. index: The index of the current element
  3. array: The array that called the map method

So, when we execute ["1","2","3"].map(parseInt), we’re actually executing:

["1","2","3"].map((item, index, array) => parseInt(item, index, array))

How the parseInt Method Works

Next, we need to understand how the parseInt method works. The parseInt method parses a string argument and returns an integer of the specified radix.

The parseInt method accepts two parameters:

  1. string: The value to be parsed. If the argument is not a string, it’s converted to a string. Leading whitespace in the string is ignored.
  2. radix: An integer between 2 and 36 that represents the radix (the base in mathematical numeral systems) of the above string. For example, specifying 10 means to use the decimal number system. Always specifying this parameter can eliminate confusion when reading the code and ensure predictable conversion results. When the radix is not specified, different implementations will produce different results, usually defaulting to 10.

Analyzing the Problem

Now, let’s analyze the execution process of ["1","2","3"].map(parseInt):

  1. For the first element “1”, the map method calls parseInt("1", 0, ["1","2","3"]). Since radix is 0, parseInt will determine the radix based on the string’s prefix. If the string doesn’t start with “0x” or “0”, the radix is 10. So, parseInt("1", 0) returns 1.

  2. For the second element “2”, the map method calls parseInt("2", 1, ["1","2","3"]). Since radix is 1, and the valid radix range is 2-36, parseInt("2", 1) returns NaN.

  3. For the third element “3”, the map method calls parseInt("3", 2, ["1","2","3"]). Since radix is 2, representing binary, and in binary, only 0 and 1 are valid, parseInt("3", 2) returns NaN.

Therefore, the return value of ["1","2","3"].map(parseInt) is [1, NaN, NaN].

How to Use Correctly

If we want to convert a string array to a number array, we can use the following methods:

["1","2","3"].map(Number)  // [1, 2, 3]

Or use an arrow function:

["1","2","3"].map(item => parseInt(item))  // [1, 2, 3]

Or use the bound function of parseInt:

["1","2","3"].map(parseInt.bind(null))  // [1, 2, 3]

Summary

This problem reveals a common trap in functional programming in JavaScript. When using higher-order functions like map, we need to pay attention to the parameters and behavior of the callback function. In this example, the parameters accepted by the parseInt function don’t completely match the parameters provided by the map method, leading to unexpected results.

Understanding this problem helps us better understand functional programming and type conversion in JavaScript.

Joy Zhao

Joy Zhao

Crafting elegant solutions to complex problems with clean code and innovative thinking. Welcome to my personal dev workspace where ideas come to life.