Symbols

Symbols

  • Symbols are a new primitive introduced in ES6. Just like the Number, String, and Boolean primitives.
  • Symbols have a Symbol function which can be used to create them.
  • The only way to make a Symbol is with the Symbol constructor:
Symbol(); // symbol
console.log(Symbol()); // prints "Symbol()" to the console
assert(typeof Symbol() === 'symbol')
new Symbol(); // TypeError: Symbol is not a constructor

Why Symbols?

  • Symbol value or just a Symbol is guaranteed to be unique.
  • Symbols are often used to add unique property keys to an object that won’t collide with keys any other code might add to the object, and which are hidden from any mechanisms other code will typically use to access the object.
  • That enables a form of weak encapsulation, or a weak form of information hiding.
let sym1 = Symbol()
let sym2 = Symbol('foo')
let sym3 = Symbol('foo')

Symbol('foo') === Symbol('foo')  // false

Global Symbol Registry

  • Symbols have individual identities and thus don’t travel across realms as smoothly as other primitive values.
  • That is a problem for symbols such as Symbol.iterator that should work across realms: If an object is iterable in one realm, it should be iterable in all realms.
  • If a library wants to provide cross-realm symbols, it has to rely on extra support, which comes in the form of the global symbol registry:
  • This registry is global to all realms and maps strings to symbols.

You ask the registry for a symbol via Symbol.for() and retrieve the string associated with a symbol (its key) via Symbol.keyFor():

> const sym = Symbol.for('Hello everybody!');
> Symbol.keyFor(sym)
'Hello everybody!'

Characteristics of Symbols

  • Symbols will never conflict with Object string keys. This makes them great for extending objects you’ve been given (e.g. as a function param) without affecting the Object in a noticeable way.
  • Symbols cannot be read using existing reflection tools.
  • Symbols are not private.
  • Symbols are not coercible into primitives.
  • Symbols are not always unique. (Symbol.for)

Well-Known Symbols

The global object Symbol has several properties that serve as constants for so-called well-known symbols. These symbols let you configure how ES6 treats an object, by using them as property keys.

  • Symbol.hasInstance: instanceof
  • Symbol.match
  • Symbol.replace
  • Symbol.iterator
  • ...
class MyClass {
    static [Symbol.hasInstance](lho) {
        return Array.isArray(lho);
    }
}
assert([] instanceof MyClass);
class MyMatcher {
    constructor(value) {
        this.value = value;
    }
    [Symbol.match](string) {
        var index = string.indexOf(this.value);
        if (index === -1) {
            return null;
        }
        return [this.value];
    }
}
var fooMatcher = 'foobar'.match(new MyMatcher('foo'));
var barMatcher = 'foobar'.match(new MyMatcher('bar'));
assert.deepEqual(fooMatcher, ['foo']);
assert.deepEqual(barMatcher, ['bar']);

Symbols

By Arfat Salman