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:
currentValue
: The current element being processedindex
: The index of the current elementarray
: The array that called themap
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:
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.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)
:
-
For the first element “1”, the
map
method callsparseInt("1", 0, ["1","2","3"])
. Sinceradix
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. -
For the second element “2”, the
map
method callsparseInt("2", 1, ["1","2","3"])
. Sinceradix
is 1, and the validradix
range is 2-36,parseInt("2", 1)
returnsNaN
. -
For the third element “3”, the
map
method callsparseInt("3", 2, ["1","2","3"])
. Sinceradix
is 2, representing binary, and in binary, only 0 and 1 are valid,parseInt("3", 2)
returnsNaN
.
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.