JavaScript Symbols

A  symbol is a unique and immutable data type that represents an identifier.

Symbols was first introduced in ECMAScript 6, and they are used to define properties of an object that cannot be accessed or modified by other parts of the code.

Creating Symbols

Declaring a symbol doesn't require the new keyword:

let mySymbol = Symbol();

We can also provide a string when creating a symbol; it acts as a label for the symbol and can help with debugging.

let anotherSymbol = Symbol('test2');

Uniqueness

Symbols are unique, even when providing a string for them:

Symbol('a') === Symbol('a')  // returns: false

Define Constants

Symbols can also be used to define constants by using them as property keys, ensuring that the property cannot be accidentally modified or deleted.

const THE_CONSTANT = Symbol();
const theAnswer = {
  [THE_CONSTANT]: 42
};
console.log(theAnswer[THE_CONSTANT]); // prints: 42

theAnswer[THE_CONSTANT] = 3.14;
console.log(theAnswer[THE_CONSTANT]);  // prints: 42

delete theAnswer[THE_CONSTANT];
console.log(theAnswer[THE_CONSTANT]);  // prints: 42

Hide Information

Symbols can be used to hide information:

let mySymbol = Symbol('answer');
let obj = {
  x: 24,
  [mySymbol]: 42
}
console.log(obj.x);         // prints: 24
console.log(obj.mySymbol);  // prints: undefined
console.log(obj[mySymbol]); // prints: 42
mySymbol.toString()  // prints: "Symbol(answer)"

One would need to keep mySymbol variable around in order to access the second obj property.

let obj = {
	x: 24,
  [Symbol("answer")]: 42
}

console.log(obj[Symbol("answer")]);  // prints: undefined

Private methods

Symbols can also be used to create complex internal logic that can't be accessed from outside the object:

const obj = {
  [Symbol.for('sum')]: function(x, y) {
    return x + y;
  },
  add: function(x, y) {
    return this[Symbol.for('sum')](x, y);
  }
};
console.log(obj.add(2, 3));  // prints: 5
console.log(obj.sum(2, 3));  // TypeError: obj.sum is not a function

Notice the use of Symbol.for to retrieve a symbol from the global symbol registry.

Global Symbol Registry

The global symbol registry is a "concept" that might not be how actually it is implemented by JS engines but it's useful for the understanding how Symbol.for and Symbol.keyFor are used to retrieve symbols and keys across different files or global scopes.

// returns: false
Symbol('sum') === Symbol('sum')  

// returns: true
Symbol.for('sum') === Symbol.for('sum')  

Symbol.keyFor(Symbol.for("sum")) === "sum"

Reading List