Live data from Hacker News

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

medium.com

61–70 of 163 posts

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

#61
post #45
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.

I'd certainly call it unintuitive if you run into it yourself and aren't aware of this, but once you unpack it we've seen it's expected behavior.

This can be said about pretty much any bug.

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

#62
post #18

Earlier quoted context omitted.

> 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 m…

> Would any of C#, C++, or TypeScript catch that C# would have a compile error with that map and parseInt definition because it can't coerce the types.

parseInt and the map callback signature both declare the second argument as integers:

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

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

The thing which would actually catch this would be the mismatch in the number of arguments (modulo someone declaring that third argument as optional) or breaking compatibility to change one of them not to be a basic integer.

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

#63
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.

The surprising bit comes in with the fact that: 1. parseInt is used with only a single argument in most cases. 2. Only the first argument of map is used in most cases. Using multiple parameters for those are so uncommon that it's easy not to realise that it's supported. _If you know all of that_ it may not be surprising to you, but in most cases there is no need for the average developer to know it, making it very su…

> in most cases there is no need for the average developer to know it

This may come off as arrogant but.. I'll proceed nonetheless. There is a need for the average developer to know the interfaces of the functions they're choosing to use. They're well documented, and the documentation is neither hard to find, nor difficult to read.

There may be an argument here for strongly typed languages -vs- weakly typed ones, where often some of the ambiguity around optional function parameters is eased, but most languages have optional function parameters, this is not in any way unique to JS. And parseInt and [].map are very common JS methods: this is not some obscure API not all devs would be unfamiliar with, these are built-ins.

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

#64

>> "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] htt…

[deleted]

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

#65
post #53
post #28

Earlier quoted context omitted.

Those are unfortunately not the same. The second one (with an explicit radix of 10) is correct; the first is not (or is at least a bit riskier). See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe... (ctrl+f for "always").

But see also https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe... and especially https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe... — that comment is increasingly stale unless you support browsers which are no longer supported by their vendors like IE8.

Good point. I've edited my comment to be more qualified.

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

#66
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.

I've developed applications in JS, but don't have extensive experience with it, and I couldn't spot the problem. Frankly, I think if `['1', '2'].map(parseInt)` is both valid and does not result in a collection containing the integers 1 and 2 in that order, that indicates a catastrophic failure of design at some level. These things happen, but usually you have to dig down to a less bog standard example to find it. The…

The problem is that this article is attributing this problem to JS, whereas the problem is with either computer science or human decimal bias: i.e. the radix is not a concept invented by JS.

If you think it should be ok for all devs to believe that parseInt === parseDecimalInt then maybe all languages should be decimal-only. That isn't the case though.

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

#67

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 ]

What does parseInt work with a radix of 0 but not 1? Neither really makes any sense.

0 is a special case where the parser tries to guess based on how the number is formatted. 1 just doesn't make sense at all.

Using 0 is the source of many interesting bugs, like when someone puts in an IP address like so:

192.168.010.001

and the client tells you it can't connect (to 192.168.8.1).

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

#68

Earlier quoted context omitted.

So it's clickbait?

The article is not clickbait but the takeaway is easily misinterpreted. Instead of "JavaScript is such a weird and confusing language" it should be "a lot of people are using JavaScript without understanding the method signatures of commonly using methods".

Those sound like two sides of the same coin.

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

#69
It is extremely awesome that JavaScript has conditioned a ton of the world's programmers to think that needing to compose your function with the identity function to achieve the desired result is not surprising or bad.

I will not be convinced that an implementation of map that gives different results when there are identity functions in the middle is doing the right thing.

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

#70

Earlier quoted context omitted.

What does parseInt work with a radix of 0 but not 1? Neither really makes any sense.

0 is a special case where the parser tries to guess based on how the number is formatted. 1 just doesn't make sense at all. Using 0 is the source of many interesting bugs, like when someone puts in an IP address like so: 192.168.010.001 and the client tells you it can't connect (to 192.168.8.1).

As of ES5 010 must be parsed as 8 if you pass in a radix of 0.
Post reply on HN