In JavaScript, the behavior of ['1', '5', '11'].map(parseInt) can be perplexing. To understand this, let's dive into how **map **and **parseInt **interact.
The map Function
The map function creates a new array by applying a provided function to each element in the array. It passes three arguments to the callback function: the element, the index, and the entire array.
The parseInt Function
The parseInt function parses a string argument and returns an integer of the specified radix (the base in mathematical numeral systems). Its signature is parseInt(string, radix).
The Interaction
When using parseInt within map, the map function inadvertently passes the index of the element as the second argument to parseInt. This causes unexpected behavior:
For the first element '1' (index 0), parseInt('1', 0) is called. The 0 radix means the base is guessed based on the string's format, defaulting to 10. Result: 1.
For the second element '5' (index 1), parseInt('5', 1) is called. But 1 is not a valid radix, so the result is NaN.
For the third element '11' (index 2), parseInt('11', 2) is called. Here, 2 means binary. The valid binary digits are 1, resulting in 3 (since 1*2^1 + 1*2^0 = 3).
The Solution
To ensure parseInt only receives the element, you can use an arrow function or another method to explicitly handle the conversion:
console.log(['1', '5', '11'].map(num => parseInt(num))); // [1, 5, 11]
Or use the Number constructor:
console.log(['1', '5', '11'].map(Number)); // [1, 5, 11]
Understanding this interaction highlights the importance of knowing how JavaScript functions interact and ensuring the correct parameters are passed to avoid unexpected results.
That's all for today.
And also, share your favourite web dev resources to help the beginners here!
Connect with me:@ LinkedIn and checkout my Portfolio.
Explore my YouTube Channel! If you find it useful.
Please give my GitHub Projects a star ⭐️
Thanks for 25659! 🤗
Top comments (13)
Nice. The tl;dr here—and the most important point—is that
parseInt
isn't an appropriate callback to.map
. The arguments thatparseInt
expects (number
,radix
) don't match the arguments passed to a.map()
callback (element
,index
,array
). You can't just pass any predefined function to.map
, you need a function intended to be a.map
callback.Also, it's best practice to always pass the second "radix" argument to
parseInt
.This is almost as bad:
Younger devs are always trying to save a few characters. The callback to
.map
should be an intentional callback to it.This is better:
Or this (note the explicit radix argument to
parseInt
):Or @lucapu88's solution (although you should use descriptive, self-documenting variable names):
Subscribe to my YouTube Channel if you find it helpful! Subscribing is free, and it will motivate me to stay active here. 😊
This very important for me. Thank you. Wish you Best in coding.
Glad to hear that❤️
Another nice share @safdarali! The title intrigued me and great reminder for using the arrow function to ensure the
parseInt
correctly receivesnum
as the parameter.Nice helpful summary too @horaceshmorace! 🤗
A parsed function is used to analyze a string argument and return an internal number on a specified base. When we use Array.prototype.map, we find an unexpected behavior that has to be parsed by arguments: a string to be analyzed and based (or radix).
The Array.prototype.map function passes several arguments for the callback function:
The value of the current element.
O index of the current element.
The original array that is being sent mapped.
When parsing is used directly as a map callback, it receives these very arguments, but it is prepared to process the data (a string and a base). The third argument (or index) interferes with the correct interpretation of the basis.
This is where this includes each element:
For the first element '1':
parseInt('1', 0) is chamado.
Base 0 is interpreted as base 10.
The result was 1.
For the second element '5':
parseInt('5', 1) é chamado.
Base 1 is invalid, has been returned to NaN.
For the third element '11':
parseInt('11', 2) is chamado.
On base 2, '11' is interpreted as 1*2^1 + 1*2^0 = 2 + 1 = 3.
The result was 3.
Correção
To avoid this behavior, you can use an anonymous function that passes the value of the current element to parse:
javascript:
const result = ['1', '5', '11'].map(str => parseInt(str));
console.log(result); // [1, 5, 11]
Alternativa com Number Constructor
Another way to convert strings to internal numbers is to use the Number constructor, which is not the case with the radix problem:
javascript:
const result = ['1', '5', '11'].map(Number);
console.log(result); // [1, 5, 11]
Full Explanation
This is an explanation of how to parse the function inside the map:
javascript
['1', '5', '11'].map(parseInt);
// Equivalent to:
['1', '5', '11'].map((elem, index) => parseInt(elem, index));
// Passos details:
parseInt('1', 0); // 1 (base 10, just base 0 tratada as base 10)
parseInt('5', 1); // NaN (base 1 invalid)
parseInt('11', 2); // 3 (base 2, 1*2^1 + 1*2^0 = 2 + 1 = 3)
However, to guarantee expected behavior, at any time you use an anonymous function or manufacturer number.
But 1 is not a valid radix, so the result is NaN.
Your this statement is wrong. 1 is a valid radix, but with 1 radix you can't have 5 as a number.
For a radix x you can have digit from 0 to x-1. And so the problem is that 5 is not a digit in radix 1.
Or: console.log(['1', '5', '11'].map(n=> +n));
Is there any real use case to pass parseInt as callback function for .map() ?
No.
parseInt
's signature isparseInt(number, radix)
..map
's callback signature isfunction(item, index, array){...}
.Each loop in
.map
will increase the radix by one, which makes no sense. You always need to provide a callback to.map
that expects the arguments that.map
passes.That is not really the issue described here. It will fail similarly with any function with more then 1 parameter.
['1', '5', '11'].map(x => +x)