Skip to content

Instantly share code, notes, and snippets.

@rpivo
Last active December 4, 2020 17:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rpivo/5869ffba661bfc2c9dbe0b4b288398c3 to your computer and use it in GitHub Desktop.
Save rpivo/5869ffba661bfc2c9dbe0b4b288398c3 to your computer and use it in GitHub Desktop.
Exploring Uniqueness in Symbols

Exploring Uniqueness in Symbols

You can make symbols out of pretty much anything.

const str = 'foo'
const num = 1
const bool = true
const arr = []
const obj = {}
const date = new Date()
const err = new Error()

// create two unique symbols from the same string registered in memory
const a = Symbol(str)
const aa = Symbol(str)

// create two unique symbols from the same number registered in memory
const b = Symbol(num)
const bb = Symbol(num)

// create two unique symbols from the same boolean registered in memory
const c = Symbol(bool)
const cc = Symbol(bool)

// construct two unique symbols from the same array registered in memory
const d = Symbol(arr)
const dd = Symbol(arr)

// construct two unique symbols from the same object registered in memory
const e = Symbol(obj)
const ee = Symbol(obj)

// construct two unique symbols from the same Date instance registered in memory
const f = Symbol(date)
const ff = Symbol(date)

// construct two unique symbols from the same Error instance registered in memory
const g = Symbol(err)
const gg = Symbol(err)

console.log(a === aa) // false
console.log(b === bb) // false
console.log(c === cc) // false
console.log(d === dd) // false
console.log(e === ee) // false
console.log(f === ff) // false
console.log(g === gg) // false
console.log(h === hh) // false

Checking for equality on each pair of Symbols that were made from the same variable registered in memory, each is false since Symbols are globally unique.

Oddly enough, you can also create Symbols from built-in objects:

const h = Symbol(Object)
const hh = Symbol(Object)

const i = Symbol(Array)
const ii = Symbol(Array)

const j = Symbol(Function)
const jj = Symbol(Function)

console.log(h === hh) // false
console.log(i === ii) // false
console.log(j === jj) // false

What if these aren't actually creating Symbols, and we're getting false on all of these equality checks because of some silent failure? Can we somehow check for truthiness to verify we're creating Symbols? Yes!

If we use Symbol's built-in for method, we can declare a Symbol into the global Symbol registry if it doesn't already exist, but if it does exist, the global registry will return the already declared Symbol.

const h = Symbol.for(Object) // Symbol from Object doesn't yet exist. Let's register one
const hh = Symbol.for(Object) // A Symbol from Object was already registered. Return it

const i = Symbol.for(Array)
const ii = Symbol.for(Array)

const j = Symbol.for(Function)
const jj = Symbol.for(Function)

console.log(h === hh) // true
console.log(i === ii) // true
console.log(j === jj) // true

Now all of our pairs are true, because the first Symbol declaration checks for a Symbol made from the given object, which doesn't yet exist, and so it creates a new Symbol from the object.

When the second Symbol declaration checks for a Symbol made from the given object, it was already registered, and for() returns that previously registered Symbol.

Taking this a step further, if we declare a third Symbol in each pair without using for(), then that Symbol will be unique since there is no registry lookup when creating that Symbol:

const h = Symbol.for(Object)
const hh = Symbol.for(Object)
const hhh = Symbol(Object) // doesn't perform a registry lookup, so it creates a new Symbol

const i = Symbol.for(Array)
const ii = Symbol.for(Array)
const iii = Symbol(Array)

const j = Symbol.for(Function)
const jj = Symbol.for(Function)
const jjj = Symbol(Function)

console.log(h === hh) // true
console.log(hh === hhh) // false
console.log(i === ii) // true
console.log(ii === iii) // false
console.log(j === jj) // true
console.log(jj === jjj) // false
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment