4

I was watching a talk on destroy all software title The Birth and Death of Javascript

during the talk Gary Bernhardt pointed out a JavaScript quirky features, were given an array of integer strings,

javascript
var a = ['10','10','10','10']
console.log(a.map(parseInt)); // [10, NaN, 2, 3, 4]

Array.map() takes a function and returns a new array with the result of applying this function on each operator.

I found the behavior incredibly bizarre at first, doesn't parseInt parse a number to an integer?

why would it be NaN? and then not 10!!

2
  • 1
    I'm not saying it's a bad question or answer, but since this is plagiarized right off your blog, I would think about removing the blog spam. Commented Jun 4, 2014 at 20:23
  • it's quite understandable, I removed the link, I had mixed feelings about linking to my blog anyway. Commented Jun 8, 2014 at 21:32

1 Answer 1

8

JavaScript is often the subject of parody, for its seemingly unexpected results.

var a = []+{} // [Object object]
var b = {}+[] // 0

However there is consistency in its madness, and I suspected the parseInt behavior must have some reason behind it.

Getting to the bottom of what's happening

I first thought of debugging parseInt, but since couldn't debug a native function, I thought of wrapping it around another function that basically does the same thing.

var a = ['10','10','10','10']
var intParse = function (x) {
    return parseInt(x);
};

console.log(a.map(parseInt)); // [10, NaN, 2, 3, 4]
console.log(a.map(intParse)); // [10,10,10,10]

Ok so it seems like everything is working fine

But just for the sake of brevity I decided to try some more observations

var a;

(a = Array(13).join('10,').split(',')).pop()  // try array of 13 '10's
a.map(parseInt); // [10, NaN, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

(a = Array(10).join('100,').split(',')).pop() // try array of 10 '100's
a.map(parseInt); // [100, NaN, 4, 9, 16, 25, 36, 49, 64, 81]

(a = Array(10).join('7,').split(',')).pop()   // try array of 10 '6's
a.map(parseInt); // [7, NaN, NaN, NaN, NaN, NaN, NaN, 6, 6, 6]

Maybe it's not that weird after all

At this point as weird as the results may seem, they are consistent (in some way), there certainly seems to be a pattern.

It then hit me. Array.map(callback) the callback takes 3 parameters, (key, index, array), so what if parseInt doesn't just take one parameter but 2 instead.

That would certainly had an effect on its results

Turns out The parseInt() function parses a string argument and returns an integer of the specified radix or base.

Syntax parseInt(string, radix);

the radix is the base of the number

parseInt("10", 0) // 10, zero meant decimal
parseInt("10", 1) // NaN, since only 0 is allowed in base 1
parseInt("10", 2) // 2, '10' in binary
parseInt("10", 3) // 3, '10' in ternary
//...

Since the second argument in map's callback is the index the radix kept changing according to the index.

This explains why my intParse function worked. I had specifically defined that it uses 'parseInt' with just x.

I thought this was what's happening inside map

var intParse = function (x) { return parseInt(x);}

When in fact this is what was happening

var intParse = function (x, r, array) { return parseInt(x, r);}

What I should've done when wrapping the function was to not assuming the arguments that where being passed like so

var a = ['10','10','10','10']
var intParse = function () {
    return parseInt.apply(this, arguments);
}
console.log(a.map(parseInt)); // [10, NaN, 2, 3, 4]
console.log(a.map(intParse)); // [10, NaN, 2, 3, 4]

Lessons learned

This was a nice exploration, I think I wound up learning a bit more than I thought I would about parseInt.

More importantly tho I was reminded that when programs act in an unexpected way, it is most likely for a reason.

Finally, if one wants to properly wrap a function use .apply(this, arguments)

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.