Numbers in JavaScript

 

 

lol

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

About Me

  • Bobby Grayson
  • @yburyug
  • 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

Hmmm

 

 

 

 

 

 

 

 

 

*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

Takeaways

  • 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

Enter `Object.is`

> 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

Object.is Rules

vs ==

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.

vs ===

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.

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

JavaScript Primitves

  • Boolean
  • String
  • Null
  • Undefined
  • Symbol
  • Number

JavaScript Primitves

  • Boolean
  • String
  • Null
  • Undefined
  • Symbol
  • Number

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.

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

Note that...

  • 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`

So...

  • 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!

http://github.com/ybur-yug/numbers-in-js-were-confusing-me

Numbers In JavaScript

By Bobby Grayson

Numbers In JavaScript

  • 1,984