Symbols & Well-Known Symbols

Guaranteed-unique keys that never collide -- and the hooks that let objects customise built-in behaviour.

Syntaxconst s = Symbol('desc'); obj[Symbol.iterator] = function* () {}; Symbol.for('shared')

A Symbol is a primitive whose whole purpose is uniqueness. Every Symbol('desc') is distinct from every other, even with the same description. As object keys they never clash with string keys or with each other, which makes them ideal for metadata and library-internal fields.

const id = Symbol('id');
obj[id] = 123;         // invisible to for...in, JSON, Object.keys

Well-known symbols: hooks into the language

Certain symbols let your objects plug into built-in operations:

  • Symbol.iterator -- makes an object work with for...of and spread.
  • Symbol.asyncIterator -- powers for await...of.
  • Symbol.toPrimitive -- controls how an object coerces to number/string.
  • Symbol.hasInstance -- customises instanceof.

Global registry

Symbol.for('key') returns the same symbol across your whole program (and across realms), useful for shared protocol keys.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Use Symbol as a unique property key on an object to avoid key collisions with library or user code.
  • Define a custom iterator on a class using Symbol.iterator so instances work with for-of loops.
  • Use a Symbol as a private-ish identifier for an internal property that library consumers should not rely on.

More examples

Symbol as unique key

Uses a computed Symbol key so the internal id property is inaccessible by the plain string 'id'.

Example · js
const id = Symbol("id");
const user = { name: "Alice", [id]: 42 };
console.log(user[id]); // 42
console.log(user.id);  // undefined – not accessible by string

Well-known Symbol.iterator

Implements Symbol.iterator on a custom class so its instances are iterable with for-of and spread.

Example · js
class Range {
  constructor(start, end) { this.start = start; this.end = end; }
  [Symbol.iterator]() {
    let current = this.start;
    const end = this.end;
    return { next: () => current <= end
      ? { value: current++, done: false }
      : { done: true } };
  }
}
console.log([...new Range(1, 4)]); // [1, 2, 3, 4]

Global symbol registry

Symbol.for creates or retrieves a shared symbol from the global registry; local Symbol() always creates a new unique one.

Example · js
const s1 = Symbol.for("app.token");
const s2 = Symbol.for("app.token");
console.log(s1 === s2); // true – same global symbol
const local = Symbol("app.token");
console.log(s1 === local); // false – different

Discussion

  • Be the first to comment on this lesson.
Symbols & Well-Known Symbols — JavaScript | SoundsCode