Live data from Hacker News

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

medium.com

11–20 of 163 posts

Re: Why ['1', '7', '11'].map(parseInt) returns [1, NaN, 3] in JavaScript

#11
post #2

Stuff like this is what drives me crazy when I work with dynamic languages like JS or PHP. I have seen a lot of code that looked perfectly fine but suffered from unexpected casts or defaults. I much prefer languages like C#, C++ or TypeScript where the compiler warns me of such problems.

Why would it drive you crazy? This is an example of someone not even knowing how the map function works.

Re: Why ['1', '7', '11'].map(parseInt) returns [1, NaN, 3] in JavaScript

#12
Disclaimer: I don't know Javascript, but that's why:

  > ['1','7','11'].map(console.log)
  1 0 [ '1', '7', '11' ]
  7 1 [ '1', '7', '11' ]
  11 2 [ '1', '7', '11' ]
  [ undefined, undefined, undefined ]
  
  > parseInt(1,0)
  1
  > parseInt(7,1)
  NaN
  > parseInt(11,2)
  3
The correct way is:

  > ['1','7','11'].map(x => parseInt(x))
  [ 1, 7, 11 ]
same as:

  > ['1','7','11'].map(x => parseInt(x, 10))
  [ 1, 7, 11 ]

Re: Why ['1', '7', '11'].map(parseInt) returns [1, NaN, 3] in JavaScript

#13
post #2

Stuff like this is what drives me crazy when I work with dynamic languages like JS or PHP. I have seen a lot of code that looked perfectly fine but suffered from unexpected casts or defaults. I much prefer languages like C#, C++ or TypeScript where the compiler warns me of such problems.

This has nothing to do with casts or defaults. Map passes multiple parameters and parseInt accepts multiple parameters. Being unaware of the functions you're using is the problem, not some sort of weird gotchas of the language. The code in the title makes multiple assumptions, and those assumptions all proved wrong.

I mean, I get that this particular example isn't really all that mysterious, but I think it's fair to say that "all parameters are optional and extra parameters are ignored" is a Javascript language gotcha.

Re: Why ['1', '7', '11'].map(parseInt) returns [1, NaN, 3] in JavaScript

#14
post #4

This isn't strange or surprising. parseInt takes two arguments, the second one is the radix and map will call with three arguments, the value, the index and the whole array. You just have to know this and it might be different in other languages. [ ... ].map(x => ...) is the right way to do this.

So it's clickbait?

Re: Why ['1', '7', '11'].map(parseInt) returns [1, NaN, 3] in JavaScript

#15
post #2

Stuff like this is what drives me crazy when I work with dynamic languages like JS or PHP. I have seen a lot of code that looked perfectly fine but suffered from unexpected casts or defaults. I much prefer languages like C#, C++ or TypeScript where the compiler warns me of such problems.

TypeScript doesn't complain about this[1], as the type of parseInt matches the type of Array.prototype.map parameter.

[1]: https://www.typescriptlang.org/play/#src=console.log(%5B'1'%...

Re: Why ['1', '7', '11'].map(parseInt) returns [1, NaN, 3] in JavaScript

#16
post #2

Stuff like this is what drives me crazy when I work with dynamic languages like JS or PHP. I have seen a lot of code that looked perfectly fine but suffered from unexpected casts or defaults. I much prefer languages like C#, C++ or TypeScript where the compiler warns me of such problems.

This has nothing to do with casts or defaults. Map passes multiple parameters and parseInt accepts multiple parameters. Being unaware of the functions you're using is the problem, not some sort of weird gotchas of the language. The code in the title makes multiple assumptions, and those assumptions all proved wrong.

A typed language would absolutely fail this at compile time.

Re: Why ['1', '7', '11'].map(parseInt) returns [1, NaN, 3] in JavaScript

#17

Easy fix ['1', '7', '11'].map(Number)

Agreed. Number is not only more obvious than parseInt for other coders but also defaults to base 10, whereas parseInt (at least historically) does not (edit: ...if you've got leading zeros, see post below).

Re: Why ['1', '7', '11'].map(parseInt) returns [1, NaN, 3] in JavaScript

#18
post #2

Stuff like this is what drives me crazy when I work with dynamic languages like JS or PHP. I have seen a lot of code that looked perfectly fine but suffered from unexpected casts or defaults. I much prefer languages like C#, C++ or TypeScript where the compiler warns me of such problems.

> I much prefer languages like C#, C++ or TypeScript where the compiler warns me of such problems.

parseInt is defined as accepting a string and an optional radix value, which is numeric. map is defined as providing the value and its index, which is also numeric. Would any of C#, C++, or TypeScript catch that without redefining either parseInt or map to require a more specific type, breaking compatibility with many millions of lines of code around the web?

Re: Why ['1', '7', '11'].map(parseInt) returns [1, NaN, 3] in JavaScript

#19
>> "If the radix provided is falsy, then by default, radix is set to 10."

The official docs for parseInt says this:

>> An integer between 2 and 36 that represents the radix (the base in mathematical numeral systems) of the string. Be careful — this does not default to 10. [1]

I just found it confusing whether the author meant the default value is 10, or if a falsy parameter (not undefined) turns out to be 10.

[1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...

Re: Why ['1', '7', '11'].map(parseInt) returns [1, NaN, 3] in JavaScript

#20
post #11
post #2

Stuff like this is what drives me crazy when I work with dynamic languages like JS or PHP. I have seen a lot of code that looked perfectly fine but suffered from unexpected casts or defaults. I much prefer languages like C#, C++ or TypeScript where the compiler warns me of such problems.

Why would it drive you crazy? This is an example of someone not even knowing how the map function works.

I would certainly consider this a "gotcha" because it's unexpected that map both deviates from the norm and the language makes it so easy to misuse and hide that misuse.

This reminds me of "array set" in Tcl (a language many probably haven't used in a long time -- or ever). Unlike the normal "set" command in Tcl, which overwrites the full value of the variable, "array set" is actually a merge operation -- it merges in new keys and doesn't get rid of anything. I've seen experienced programmers use "array set" in a loop, leading to awful bugs. This too could be dismissed by saying that they "don't even know how array set works," but actually I place the blame on the language for making it so easy to misuse.

Post reply on HN