Is Javascript Broken? #1

Meyron Levanon
3 min readJun 23, 2020

--

Many people like to bash javascript (js) with seemingly weird code examples that spew unexpected results. In some cases, those are the result of a truly weird js property or some legacy feature. However in most cases, js works just fine, as long as you read the fine print. Here’s one example I found on Twitter:

This is wild! Trying to run this example in the console gives us this:

Since map is an array function that accepts a transform function and returns an array with the transformed array elements, and parseInt turns a string representation of a number into an actual number, we expect this expression to return an array containing five elements, all should be the number 12. but we’re getting a different number every time. We’re even getting NaN, which literally means “Not a number”. Is js broken?

Luckily, it is not. This expression does exactly what we expect it to do. It is us who need a refresher course on these two functions. Let’s look at these function signatures:

Number.parseInt(string, radix)

array.map(function(currentValue, index, arr), thisValue)

That’s interesting. Looks like map passes a few arguments to the transform function, and looks like parseInt can receive more than one argument. More specifically, it looks like we’re calling each element on the array with its value, and its index, whereas parseInt uses that index as a radix (or base). Let’s see how this gets us to our result.

Number.parseInt(“12”, 0) - There is no such thing as base 0. To make this more symbolic - in js, 0 is a “falsy” value, which means that when parseInt asks if(radix) to check if it exists, that expression is evaluated as false, making this equivalent to just Number.parseInt(“12”); which of course, returns 12.

Number.parseInt(“12”, 1) - There is no “2” in base 1. Actually there’s no “1” as well, which makes this number invalid, or in other words, Not A Number (NaN)

Number.parseInt(“12”, 2) - This returns 1. Wait. What? There is no 2 in base 2, Only 1 and 0. Why does this not return NaN? Looking more into parseInt documentation reveals that parseInt returns NaN only if the first number of the string can’t be converted into the relevant base, so actually, parseInt(“123”, 2) returns 1 as well. Heck, even parseInt(“1acb”, 2) returns 1.

Number.parseInt(“12”, 3) — This returns 5 as expected. 12 in base 3 = 5.

Number.parseInt(“12”, 4) — This returns 6 as expected. 12 in base 4 = 6.

Mystery solved! But lets try modifying the original expression to do what we intuitively think it does. We just need to be explicit about our arguments and not assume js knows what we think. You remember what they say about assuming…

Original expression:

“12,12,12,12,12”.split(“,”).map(Number.parseInt)

Fixed expression version 1 (Calling functions with explicit arguments):

“12,12,12,12,12”.split(“,”).map(value => Number.parseInt(value))

Fixed expression version 2 (Calling a function that only accepts one arg):
There are other functions that convert to numbers, that take one parameter only, like: Number(object) or parseFloat(string), these will ignore any extra params.

“12,12,12,12,12”.split(“,”).map(Number)

Javascript is saved! It’s still weird, but it works :)

--

--

Meyron Levanon

Fullstack software developer. I enjoy debates, fine foods, and good looking code. 😎