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
So what does JavaScript do when dividing by zero? "NaN" maybe? Nope, it goes for infinity.
console.log(1/0) // Infinity
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
Okay, so infinity doesn't seem to be a type, then? Let's test:
console.log(typeof Infinity) // number
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
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
}
}
Seems logical to a beginner, but here's the culprit
console.log(typeof null) // object
console.log(typeof null === typeof {}) // true
But then again, we all know objects aren't object anyway, right?
console.log({} === {}) // false
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
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)
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.
I completely agree. This is, without a doubt, the worst-built language ever. I even wrote an entire article about why I hate it.
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.
That's true.