Quiz

What are `Symbol`s used for in JavaScript?

Topics
JavaScript
Edit on GitHub

TL;DR

Symbols in JavaScript are a new primitive data type introduced in ES6 (ECMAScript 2015). They are unique and immutable identifiers that is primarily for object property keys to avoid name collisions. These values can be created using Symbol(...) function, and each Symbol value is guaranteed to be unique, even if they have the same key/description. Symbol properties are not enumerable in for...in loops or Object.keys(), making them suitable for creating private/internal object state.

let sym1 = Symbol();
let sym2 = Symbol('myKey');
console.log(typeof sym1); // "symbol"
console.log(sym1 === sym2); // false, because each symbol is unique
let obj = {};
let sym = Symbol('uniqueKey');
obj[sym] = 'value';
console.log(obj[sym]); // "value"

Note: The Symbol() function must be called without the new keyword. It is not exactly a constructor because it can only be called as a function instead of with new Symbol().


Symbols in JavaScript

Symbols in JavaScript are a unique and immutable data type used primarily for object property keys to avoid name collisions.

Key characteristics

  • Uniqueness: Each Symbol value is unique, even if they have the same description.
  • Immutability: Symbol values are immutable, meaning their value cannot be changed.
  • Non-enumerable: Symbol properties are not included in for...in loops or Object.keys().

Creating Symbols

Symbols can be created using the Symbol() function:

const sym1 = Symbol();
const sym2 = Symbol('uniqueKey');
console.log(typeof sym1); // "symbol"
console.log(sym1 === sym2); // false, because each symbol is unique

The Symbol(..) function must be called without the new keyword.

Using Symbols as object property keys

Symbols can be used to add properties to an object without risk of name collision:

const obj = {};
const sym = Symbol('uniqueKey');
obj[sym] = 'value';
console.log(obj[sym]); // "value"

Symbols are not enumerable

  • Symbol properties are not included in for...in loops or Object.keys().
  • This makes them suitable for creating private/internal object state.
  • Use Object.getOwnPropertySymbols(obj) to get all symbol properties on an object.
const mySymbol = Symbol('privateProperty');
const obj = {
name: 'John',
[mySymbol]: 42,
};
console.log(Object.keys(obj)); // Output: ['name']
console.log(obj[mySymbol]); // Output: 42

Global Symbol registry

You can create global Symbols using Symbol.for('key'), which creates a new Symbol in the global registry if it doesn't exist, or returns the existing one. This allows you to reuse Symbols across different parts of your code base or even across different code bases.

const globalSym1 = Symbol.for('globalKey');
const globalSym2 = Symbol.for('globalKey');
console.log(globalSym1 === globalSym2); // true
const key = Symbol.keyFor(globalSym1);
console.log(key); // "globalKey"

Well-known Symbol

JavaScript includes several built-in Symbols, referred as well-known Symbols.

  • Symbol.iterator: Defines the default iterator for an object.
  • Symbol.toStringTag: Used to create a string description for an object.
  • Symbol.hasInstance: Used to determine if an object is an instance of a constructor.

Symbol.iterator

let iterable = {
[Symbol.iterator]() {
let step = 0;
return {
next() {
step++;
if (step <= 5) {
return { value: step, done: false };
}
return { done: true };
},
};
},
};
for (let value of iterable) {
console.log(value); // 1, 2, 3, 4, 5
}

Symbol.toStringTag

let myObj = {
[Symbol.toStringTag]: 'MyCustomObject',
};
console.log(Object.prototype.toString.call(myObj)); // "[object MyCustomObject]"

Summary

Symbols are a powerful feature in JavaScript, especially useful for creating unique object properties and customizing object behavior. They provide a means to create hidden properties, preventing accidental access or modification, which is particularly beneficial in large-scale applications and libraries.

Further reading

Edit on GitHub