Reading — step 1 of 7
Learn
Symbol is a primitive type added in ES2015. Each Symbol is unique — Symbol() !== Symbol() even with the same description. They're used for non-colliding object keys and as protocol identifiers.
Creating symbols
The description is purely for console.log / .toString(). It doesn't affect identity.
Symbols as object keys
Symbols can be property keys, sitting alongside string keys but invisible to most enumeration:
This isn't true encapsulation (anyone with the symbol can access), but it prevents accidental collision and skips standard enumeration.
Symbol.for() — the global registry
For symbols that should be shared across modules / realms:
Symbol.for(key) returns the registry's symbol for key, creating it if it doesn't exist. Use sparingly — it's a global.
Well-known symbols — protocol customization
The language defines special symbols on Symbol that interact with built-in operations. Implementing them lets your objects participate in language protocols.
Symbol.iterator — for...of and spread:
Symbol.asyncIterator — for await...of (async iteration).
Symbol.toPrimitive — coercion to primitive:
Symbol.hasInstance — customize instanceof:
Symbol.toStringTag — name shown by Object.prototype.toString:
Common mistakes
- Treating Symbol() === Symbol() as true — never. Use Symbol.for() for shared symbols.
- Expecting symbols in JSON output — they're skipped by JSON.stringify.
- Using symbols for true privacy — anyone can extract them with getOwnPropertySymbols. Use private fields (#name) for real encapsulation.
- Forgetting computed-property syntax —
[symbol]: value(with brackets) is required when defining symbol-keyed properties in object literals. - Assuming Symbol.iterator on arrays/strings is the same — they share the protocol but each has its own implementation.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…