DEV Community

Cover image for Why['1','5','11'].map(parseInt) returns [1, NaN, 3] in Javascript
Safdar Ali
Safdar Ali

Posted on

Why['1','5','11'].map(parseInt) returns [1, NaN, 3] in Javascript

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:

parseInt broken

  • 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]
Enter fullscreen mode Exit fullscreen mode

Or use the Number constructor:

console.log(['1', '5', '11'].map(Number)); // [1, 5, 11]
Enter fullscreen mode Exit fullscreen mode

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)

Collapse
 
horaceshmorace profile image
Horace Nelson

Nice. The tl;dr here—and the most important point—is that parseInt isn't an appropriate callback to .map. The arguments that parseInt 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.

Collapse
 
coolerhansen profile image
CoolerHansen

This is almost as bad:

console.log(['1', '5', '11'].map(Number));
Enter fullscreen mode Exit fullscreen mode

Younger devs are always trying to save a few characters. The callback to .map should be an intentional callback to it.

This is better:

console.log(['1', '5', '11'].map(num => Number(num));
Enter fullscreen mode Exit fullscreen mode

Or this (note the explicit radix argument to parseInt):

console.log(['1', '5', '11'].map(num => parseInt(num, 10));
Enter fullscreen mode Exit fullscreen mode

Or @lucapu88's solution (although you should use descriptive, self-documenting variable names):

console.log(['1', '5', '11'].map(n=> +n));
Enter fullscreen mode Exit fullscreen mode
Collapse
 
safdarali profile image
Safdar Ali

Subscribe to my YouTube Channel if you find it helpful! Subscribing is free, and it will motivate me to stay active here. 😊

Collapse
 
qbts_load_1d475b5619cf613 profile image
qbts load

This very important for me. Thank you. Wish you Best in coding.

Collapse
 
safdarali profile image
Safdar Ali

Glad to hear that❤️

Collapse
 
ashleyd480 profile image
Ashley D

Another nice share @safdarali! The title intrigued me and great reminder for using the arrow function to ensure the parseInt correctly receives num as the parameter.
Nice helpful summary too @horaceshmorace! 🤗

Collapse
 
little_oak profile image
João Paulo Santos ✪

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.

Collapse
 
sudhirkumar1003 profile image
Sudhir Kumar • Edited

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.

Collapse
 
lucapu88 profile image
Luca Caputo

Or: console.log(['1', '5', '11'].map(n=> +n));

Collapse
 
syakirurahman profile image
Syakir

Is there any real use case to pass parseInt as callback function for .map() ?

Collapse
 
horaceshmorace profile image
Horace Nelson

No.

parseInt's signature is parseInt(number, radix).

.map's callback signature is function(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.

Collapse
 
retakenroots profile image
Rene Kootstra

That is not really the issue described here. It will fail similarly with any function with more then 1 parameter.

Collapse
 
quocboy159 profile image
quocboy159

['1', '5', '11'].map(x => +x)