DEV Community

neoan
neoan

Posted on

The humor of JavaScript

As the year marks its end and we are therefore exposed to the yearly "What to use in 2024" click-bait articles, let's instead amuse us with some oddities of JavaScript.

Numbers

You can't divide by zero. But why not? If I divide 1 by smaller and smaller fractions, I'll be getting higher and higher numbers nearing infinity. So eventually we'd end up at infinity? Not so fast. If we "came from the other side" towards zero, we'd approach negative infinity when getting to zero:

const a = 1/0.0001; // 1,000
const b = 1/0.000001; // 100,0000

const c = 1/-0.000001; // -100,0000
const d = 1/-0.0000001; // -1,000,0000
Enter fullscreen mode Exit fullscreen mode

So what does JavaScript do when dividing by zero? "NaN" maybe? Nope, it goes for infinity.

console.log(1/0) // Infinity
Enter fullscreen mode Exit fullscreen mode

Interesting. That means that the type of 1/0 must be infinity? Nope, it's NaN (Not a number).

console.log(typeof 1/0) // NaN
Enter fullscreen mode Exit fullscreen mode

Okay, so infinity doesn't seem to be a type, then? Let's test:

console.log(typeof Infinity) // number
Enter fullscreen mode Exit fullscreen mode

Wait a second, you think? If infinity is a number and 1/0 is infinity, why is the type of 1/0 not a number (NaN)? Well, let's explore:

console.log(typeof NaN) // number
console.log(NaN === NaN) // false
Enter fullscreen mode Exit fullscreen mode

Confused, yet?

Objects

What's so nice about having no type safety is that we can be quick & dirty. So dirty indeed, that nearly every company will insist on Typescript to avoid almost impossible to find bugs. Let's examine the following code.

let myObject = null;

function getFromBackend(){
  fetch('/api/object').then(j => j.json()).then(result => {
    // result: {a: "b"}
    myObject = result;
  })
}

// SpongeBob narrator: ..several hours later

// Is our variable myObject filled?
function checkIfValid(){
  if(typeof myObject === 'object'){
   // do something
  }
}

Enter fullscreen mode Exit fullscreen mode

Seems logical to a beginner, but here's the culprit

console.log(typeof null) // object
console.log(typeof null === typeof {}) // true
Enter fullscreen mode Exit fullscreen mode

But then again, we all know objects aren't object anyway, right?

console.log({} === {}) // false
Enter fullscreen mode Exit fullscreen mode

OMG, what a language

Using the type-safe comparison (===) is therefore a must, as otherwise the nightmare would be so much worse:

const array = []
console.log(array == false) // true
console.log(array === false) // false
Enter fullscreen mode Exit fullscreen mode

There are even books about JavaScript oddities, as this list could go on for a while. But I guess we'd rather go on reddit to bash on PHP so Santa doesn't put us on the naughty list ;-)

Top comments (5)

Collapse
 
Sloan, the sloth mascot
Comment deleted
Collapse
 
sroehrl profile image
neoan

You misinterpreted my intended tone if you think I am "bashing JavaScript", a language I use on a daily basis. But humor is a good way to learn and face frustration.

But nonetheless, I gladly go into some of your points.

Longevity

First of all, that's not really true for JavaScript. Some scripts designed for some 90s version of IE might use "Pre-ECMA, only works in this specific browser and version" tweaks that simply crash today. But leaving that aside, endless backwards compatibility introduces almost as many cons as pros when it comes to security and growth of a language. Think of markup languages like CSS or HTML. Do you really think if the web needed to be started from scratch this is how we would construct webpages today? Don't you see how we just build tool on top of tool to make these "documents" interactive masterpieces?

Anyway, about your technical points:

The "choice" for Infinity was driven by float allocation limits, not by concerns about errors (after all, it's easy to avoid and test).

Your absolutely correct about the typeof 1/0. Like many other examples I used, knowing what actually happens while the interpreter hoists & parses clears up some of the confusion.

However, some minor details: NaN is a global property, only {} actually creates an instance. Likewise, many loosely typed languages kept a difference between type safe and simple comparators. Not for backwards compatability, but because sometimes the difference comes in handy (if it's nothing, do you always need to know if it's null, undefined, or zero?)

I find your last paragraph unnecessarily hostile for a comment on an obviously light-hearted take. I don't know why my words triggered you so much, but I recommend not reading watercoolers as some kind of attack.

Collapse
 
kaamkiya profile image
Kaamkiya

I completely agree. This is, without a doubt, the worst-built language ever. I even wrote an entire article about why I hate it.

Collapse
 
sroehrl profile image
neoan

Well, there's some charm in dirty languages. It makes functionality less verbose while allowing you to write clean, predictable code if you now what you are doing.

Collapse
 
kaamkiya profile image
Kaamkiya

That's true.