lol
A dive into types, equality, and ECMAScript 2016 specifications
Someone shared this code snipped from V8
*spelunking begins*
I've never seen a -0 before...
> -0 === 0 // I always start with strict equality, because JS
true
> -0 == 0 // As expected
true
> -0 == +0 // Alright....maybe its just because `==`
true
> -0 === +0 // Well...shit
true
> -0 / 0 // Reasonable
NaN
> -0 / 1 // Okay..
-0
> 1 / -0 // as expected
-Infinity
> 1 / +0 // Normal Enough
Infinity
> +0 == 0 // Alright, the inverse of our first bit works
true
> +0 === 0 // And confirms itself.
true
Let's play in the console
> Object.is(-0, +0) // Well, shit
false
> Object.is(-0, -0) // Well, this is reasonable
true
> Object.is(-0, 0) // Hmmmm
false
> Object.is(+0, 0) // It seems `0` _really_ is aliased as `+0`
true
This is not the same as being equal according to the == operator. The == operator applies various coercions to both sides (if they are not the same Type) before testing for equality (resulting in such behavior as "" == false being true), but Object.is doesn't coerce either value.
This is also not the same as being equal according to the === operator. The === operator (and the == operator as well) treats the number values -0 and +0 as equal and treats Number.NaN as not equal to NaN.
From the spec:
4.3.2 primitive value
member of one of the types Undefined, Null, Boolean, Number, Symbol, or String as defined in clause 6.
NOTE:
A primitive value is a datum that is represented directly at the lowest level of the language implementation.
> new Number
[Number: 0]
> new Number(-0)
[Number: -0]
> new Number(+0)
[Number: 0]
> new Number(0)
[Number: 0]
> one = new Number(1)
[Number: 1]
> one == 1
true
> one === 1
true
> Object.is(one, 1)
false
Per ECMAScript 2016