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 themapmethod
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
mapmethod callsparseInt("1", 0, ["1","2","3"]). Sinceradixis 0,parseIntwill 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
mapmethod callsparseInt("2", 1, ["1","2","3"]). Sinceradixis 1, and the validradixrange is 2-36,parseInt("2", 1)returnsNaN. -
For the third element “3”, the
mapmethod callsparseInt("3", 2, ["1","2","3"]). Sinceradixis 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.