+-0, NaN and Object.is in JavaScript
- Published at
- Updated at
- Reading time
- 2min
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!
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
, 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
!
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
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
differentiates positive and negative zeros and it's even able to detect NaN
. ๐
I saw Object
for the first time in Mathias' slides, and it doesn't seem to be used that often. Do you have Object
in your source code?
Additional resources
Join 5.5k readers and learn something new every week with Web Weekly.