In JavaScript, the map function applies a given function to each element of an array and returns a new array with the results. When you use map with parseInt like ['1', '5', '11'].map(parseInt), the result might not be what you expect due to the way parseInt and map interact. Let's break down what happens.
Understanding parseInt
The parseInt function in JavaScript parses a string argument and returns an integer of the specified radix (the base in mathematical numeral systems).
parseInt(string, radix)
-
string
: The string to be parsed. -
radix
: An integer between 2 and 36 that represents the radix (the base in mathematical numeral systems) of the string.
If radix is not provided, parseInt will use different heuristics to determine the base of the string, which can lead to unexpected results.
The map Function
The map function calls the provided function once for each element in an array, in order, and constructs a new array from the results.
array.map(function(currentValue, index, array) {
// function body
})
-
currentValue
: The current element being processed in the array. -
index
: The index of the current element being processed in the array. -
array
: The array map was called upon.
Combining map and parseInt
When you use parseInt inside map, parseInt is called with two arguments: the element of the array and the index of that element. However, parseInt can take two arguments where the second argument is the radix. So, the index is inadvertently used as the radix.
Here's how it breaks down:
For the first element '1' at index 0:
parseInt('1', 0) // 0 is interpreted as the radix, which defaults to 10
// Result: 1
For the second element '5' at index 1:
parseInt('5', 1) // 1 is interpreted as the radix, but radix 1 is invalid
// Result: NaN (Not a Number)
For the third element '11' at index 2:
parseInt('11', 2) // 2 is interpreted as the radix (binary)
// '11' in binary is 3 in decimal
// Result: 3
Thus, ['1', '5', '11'].map(parseInt)
results in [1, NaN, 3]
.
Correct Usage
To avoid this issue, you can pass a function that only uses the first argument of parseInt and defaults the radix to 10:
['1', '5', '11'].map(str => parseInt(str, 10)) // [1, 5, 11]
or just ommit the radix
param:
['1', '5', '11'].map(str => parseInt(str)) // [1, 5, 11]
Here, str is explicitly converted to an integer using a base of 10 for each element in the array, resulting in [1, 5, 11].
Cover image and article content created with the help of AI
Top comments (1)
This is a very real source of difficult-to-debug issues. Knowing or limiting the number of arguments on both the caller and the callee can be very important.
Libraries like Lo-dash have offered a
_.unary()
utility to provide this kind of protection as well, but that is more helpful when you are composing functions or do not have full control of the function passed to you. Of course this became much easier since ES6 and arrow functions.