Symbols and Well-Known Symbols

A guaranteed-unique primitive type, used as a collision-free object key and to hook user objects into built-in language behavior via well-known symbols.

                Symbol(description) / Symbol.iterator / Symbol.toPrimitive
              

Purpose

Symbol() creates a new, guaranteed-unique primitive value, useful as an object key that can never collide with a string key or another symbol. A well-known symbol is a specific, predefined symbol the specification uses to let user code hook into built-in behavior.

Syntax

const s1 = Symbol('id');
const s2 = Symbol('id');
s1 === s2; // false — always, regardless of matching descriptions

class Range {
  [Symbol.toPrimitive](hint) {
    return hint === 'string' ? 'a range' : 42;
  }
}

Common well-known symbols

  • Symbol.iterator: makes an object work with for...of and spread (recall Generators and Iterators).
  • Symbol.toPrimitive: customizes the ToPrimitive coercion algorithm for an object.
  • Symbol.toStringTag: customizes what Object.prototype.toString.call(obj) reports.
  • Symbol.hasInstance: customizes what instanceof reports for a class.

Behavior notes

  • Symbol-keyed properties never appear in Object.keys(), for...in, or JSON.stringify() — a deliberate way to attach metadata to an object without polluting its enumerable, string-keyed surface.
  • Symbol.for(key) creates or retrieves a symbol from a global registry, shared across realms — distinct from Symbol(description), which always creates a new, unique symbol regardless of a matching description.
  • Object.getOwnPropertySymbols(obj) is the dedicated way to inspect an object’s symbol keys, since they’re invisible to the usual enumeration methods.

Common mistakes

  • Assuming two symbols with the same description are equal — they’re never === equal unless created via Symbol.for with the same key.
  • Using a symbol key expecting it to be a genuine security boundary — it hides a property from casual enumeration, but Object.getOwnPropertySymbols can still discover it.

Runtime notes

Core ECMAScript (ES2015), identical behavior across every current browser and Node version.

Taught in these lessons

Related reference