Published at
Updated at
Reading time
2min
This post is part of my Today I learned series in which I share all my web development learnings.

I was in Cluj-Napoca the last few days to speak at the excellent JSHeroes conference and saw a fascinating code snippet in Mathias Bynens' talk "V8 Internals for JS Developers" (the recording is from a different event).

Object.is(-0, +0); // false

This single line is fascinating in two ways โ€“ let's have a look!

The two existent zeros in JavaScript

First, JavaScript numbers follow the IEEE Standard for Floating-Point Arithmetic. This standard is available in several variants, and JavaScript uses "Double precision" (also called "binary64") based on 64 bits.

IEEE 754 defines that a sign, a significant, and an exponent to describe each finite number. Understanding how this works may take some time, but the important fact is that one bit (the sign bit) in JavaScript numbers defines if a number is positive or negative. And this definition includes the number zero!

Yes there are negative zeros in JavaScript!

const posNumber = 1;
const negNumber = -1;
const posZero = +0;
const negZero = -0;

My first reaction to discovering negative zeros was that I surely don't have these in my code, but you will be surprised! Round -0.23, and you'll end up with a negative zero. So it might be possible that you have to treat negative zeros in your code, too.

Math.round(-0.23); // -0

But there's more; compare a positive and negative zero and you'll discover that they're treated equal! ๐Ÿ˜ฒ

-0 === +0 // true

Sidenote: you can differentiate -0 and 0 by using division and the resulting Infinity. Positive and negative Infinity are not equal.

1 / -0 === -Infinity    // true 
1 / 0 === Infinity      // true
-Infinity === Infinity  // false

But there's a nicer way of dealing with -0!

Object.is โ€“ comparing without quirks?

Strict comparison with === treats 0 and -0 as equal and it just feels like another JavaScript quirk that we all learn over time. It's similar to NaN, which is not equal to itself.

NaN === NaN // false

// Tip: you can use Number.isNaN as an alternative
Number.isNaN(NaN) // true

These quirks are when Object.is comes into play. In most cases, it behaves the same as ===, but it includes some minor "improvements" making things more logical. Let's look at the zero and NaN example.

Object.is(-0, 0);    // false
Object.is(NaN, NaN); // true

Object.is differentiates positive and negative zeros and it's even able to detect NaN. ๐ŸŽ‰

I saw Object.is for the first time in Mathias' slides, and it doesn't seem to be used that often. Do you have Object.is in your source code?

Additional resources

Was this TIL post helpful?
Yes? Cool! You might want to check out Web Weekly for more quick learnings. The last edition went out 11 days ago.
Stefan standing in the park in front of a green background

About Stefan Judis

Frontend nerd with over ten years of experience, freelance dev, "Today I Learned" blogger, conference speaker, and Open Source maintainer.

Related Topics

Related Articles