A dive into types, equality, and ECMAScript 2016 specifications
About This Talk
- Highly technical
- Largely frivolous
- (Almost) never should affect your day-to-day life
- Doesn't actually have the answers to my questions
- Might still be kind of fun
- Bobby Grayson
- Normally Known As Red Leather Pants Here
- Dev @ Cometa Works
- Likes cats
Welp, let's go...
So the other day I saw something weird
Someone shared this code snipped from V8
Programmers only ever pick arbitrary numbers that are powers of 2
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
- It seems like +0 is aliased to 0
- It seems like they all behave the same
- I'm sure this isnt truly the case
Let's go a little deeper
> 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
- both arguments are Undefined
- both arguments are Null
- both arguments are True or both False
- both arguments are String primitives of the same length with the same characters
- both arguments are the same Object
both arguments are Number types and
- both arguments are +0
- both arguments are -0
- both arguments are NaN
- or both arguments are non-zero and both not NaN and both have the same value
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.
More Object.is Rules
An Aside: Lol Coercion
Some Observations Before Going Further
- It says 'number types', not objects
- Numbers are a primitive, right?
- Primitives arent objects, right?
- This is clearly just gonna keep getting weirder
Number Specification Overview
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.
A primitive value is a datum that is represented directly at the lowest level of the language implementation.
From the `Number` Overview
> 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
The Full Number Specification
Per ECMAScript 2016
Some Interesting Points
- The spec keeps saying 'integer', but everything is floats per the IEEE specification
- It seems numbers are both an object and a primitive but there is little to distinguish at what point one becomes the other
- I get nervous anytime a single definition clause has 4+ "Note that..."s
Let's Look at `Object`
- An Objects prototype can be the Null value
- The Null value is a primitive, but a Prototype is not
- If a Prototype holds only the Null value, does it have any properties at all?
- If it has no properties, is it then equivalent to Null?
- If Null is a primitive and a Prototype can be Null and a Prototype is a type of Object, does that mean all Primitives are?
I think it might lead here...
I have answers to none of these questions, yet
But I'm working on it!
By Bobby Grayson