📜 ⬆️ ⬇️

Why ['1', '7', '11']. Map (parseInt) returns [1, NaN, 3] in Javascript?


Javascript is weird. Do not believe? Well, then try to convert the array of strings to integers using map and parseInt . Launch the console (F12 on Chrome), paste the code below and press Enter


['1', '7', '11'].map(parseInt); 

Instead of the expected array of integers [1, 7, 11], we get [1, NaN, 3] . But how? To find out what's the matter, we first have to talk about some basic concepts of Javascript. If you need TL; DR, scroll through the article to the very end.


Truth and Falsity


Here is a simple if-else statement in Javascript:


 if (true) { //   } else { //    } 

In this case, the condition of the statement is always true, so the if block is always executed, and the else block is always ignored. This is a trivial example, because true is a boolean type. What then if we set a non boolean condition?


 if ("hello world") { //  ? console.log(" "); } else { //  ? console.log(" "); } 

Try running this code in the developer console. You should see the “Condition true” because the string “hello world” is perceived as true .


Each object in Javascript is perceived as either true or false . When placed in a logical context, such as an if-else statement, the objects are treated as true or false based on their “truth”. Which objects are true and which are false? The simple rule applies:


All values ​​are true, except for: false , 0 , "" (empty string), null , undefined , and NaN .


Counter intuitively, this means that the string "false" , the string "0" , the empty object {} and the empty array [] are true. You can verify this yourself by passing the Boolean function to any of the objects above (for example, Boolean ("0"); ).


But for our purposes, it’s enough just to remember that 0 is a lie.


The base of the number system


 0 1 2 3 4 5 6 7 8 9 10 

When we count from zero to nine, we use different symbols for each of the numbers (0-9). However, as soon as we reach ten, we need two different characters (1 and 0) to represent the number. This is due to the fact that we use the decimal number system.


The base is the smallest number that cannot be represented by just one symbol. Different number systems have different bases, and therefore, the same numbers may indicate different numbers.


 DECIMAL BINARY HEXADECIMAL RADIX=10 RADIX=2 RADIX=16 0 0 0 1 1 1 2 10 2 3 11 3 4 100 4 5 101 5 6 110 6 7 111 7 8 1000 8 9 1001 9 10 1010 A 11 1011 B 12 1100 C 13 1101 D 14 1110 E 15 1111 F 16 10000 10 17 10001 11 

For example, the numbers 11 denote different numbers in these three number systems. For binary, it is 3. For hexadecimal, this is 17.


The attentive reader probably noticed that the code with parseInt returns 3 when the input is 11, which corresponds to the binary column from the table above.


Function arguments


Javascript functions can be called with any number of arguments, even if their number in the signature is excellent. Missing parameters are treated as undefined, and additional parameters are simply ignored (but stored in an arguments object that looks like an array).


 function foo(x, y) { console.log(x); console.log(y); } foo(1, 2); //  1, 2 foo(1); //  1, undefined foo(1, 2, 3); //  1, 2 

map ()


We are almost there!


Map is a method in an array prototype that returns a new array from the results of a function call for each element of the original array. For example, the following code multiplies each element of an array by 3:


 function multiplyBy3(x) { return x * 3; } const result = [1, 2, 3, 4, 5].map(multiplyBy3); console.log(result); //  [3, 6, 9, 12, 15]; 

Now suppose I want to output each element using map () (and not using return ). You can just pass console.log as an argument to map () ... right?


 [1, 2, 3, 4, 5].map(console.log); 


Something strange is happening. Instead of outputting only a value, each console.log call prints the index and array in its entirety.


 [1, 2, 3, 4, 5].map(console.log); // : [1, 2, 3, 4, 5].map( (val, index, array) => console.log(val, index, array) ); //   : [1, 2, 3, 4, 5].map( val => console.log(val) ); 

When passing a function to map () at each iteration, it will receive three arguments: currentValue , currentIndex, and the full array . That is why at each iteration three records are displayed.


Now we have everything you need to solve a mystery.


Together


ParseInt takes two arguments: string and radix (base). If the transmitted radix is false, then the default is set to 10.


 parseInt('11'); => 11 parseInt('11', 2); => 3 parseInt('11', 16); => 17 parseInt('11', undefined); => 11 (radix ) parseInt('11', 0); => 11 (radix ) 

Let's look at this example step by step.


 ['1', '7', '11'].map(parseInt); => [1, NaN, 3] //  : val = '1', index = 0, array = ['1', '7', '11'] parseInt('1', 0, ['1', '7', '11']); => 1 

Since 0 is false, the default value for the base is 10 . parseInt () takes only two arguments, so the third argument ['1', '7', '11'] is ignored. The string '1' at base 10 gives the result 1 .


 //  : val = '7', index = 1, array = ['1', '7', '11'] parseInt('7', 1, ['1', '7', '11']); => NaN 

In the system at the base of 1 character '7' does not exist. As with the first iteration, the last argument is ignored. Thus parseInt () returns NaN .


 //  : val = '11', index = 2, array = ['1', '7', '11'] parseInt('11', 2, ['1', '7', '11']); => 3 

In the binary number system, '11' refers to the number 3 . The last argument is again ignored.


Total (TL; DR)


['1', '7', '11']. Map (parseInt) does not work as intended because map passes three arguments to parseInt () at each iteration. The second argument, index, is passed to parseInt as the radix parameter (base of the number system). Thus, each line in the array is analyzed using a non-default basis. '7' is analyzed by base 1 , which gives NaN ; '11' is analyzed as a binary number - a total of 3 . '1' is analyzed by default base 10 , because its index 0 is false.


And here is the code that will work the way we wanted:


 ['1', '7', '11'].map(numStr => parseInt(numStr)); 



')

Source: https://habr.com/ru/post/456344/


All Articles