Symbol
The Symbol Primitive in JavaScript
Unique identifiers, hidden object properties, and Well-Known engine customization hooks.
The Biometric Retinal Keypass
Introduced in ES6, `Symbol` is a primitive data type that is guaranteed to be completely unique and immutable. It enables non-colliding object keys and deep customization of built-in language semantics.
Guaranteed Uniqueness
Every call to `Symbol("desc")` returns a distinct symbol. `Symbol("id") === Symbol("id")` evaluates to `false`.
Non-Colliding Object Keys
Symbol properties do not show up in `for...in` loops, `Object.keys()`, or `JSON.stringify()`. They prevent accidental name collisions in shared libraries.
Reflective Access
To retrieve symbol keys on an object, use `Object.getOwnPropertySymbols(obj)` or `Reflect.ownKeys(obj)`.
Well-Known Symbols
Built-in symbols exposed as `Symbol.*` customize engine operations: `Symbol.iterator` (custom iteration), `Symbol.toPrimitive` (type coercion), `Symbol.hasInstance` (`instanceof` behavior).
Global Symbol Registry
`Symbol.for("key")` checks the global cross-realm registry and returns a shared symbol if it exists, or creates one. `Symbol.keyFor(sym)` returns its string key.
Using symbols for collision-free properties and implementing Symbol.toPrimitive:
// 1. Guaranteed Unique Keys
const idSymbol = Symbol("internal_id");
const user = {
name: "Sarah Connor",
[idSymbol]: "T-800-HUNTER"
};
console.log("Object.keys:", Object.keys(user)); // Only ['name']
console.log("Direct symbol read:", user[idSymbol]); // 'T-800-HUNTER'
// 2. Customizing Coercion with Well-Known Symbol.toPrimitive
const money = {
amount: 250,
currency: "USD",
[Symbol.toPrimitive](hint) {
if (hint === "string") return `${this.amount} ${this.currency}`;
return this.amount; // default or number
}
};
console.log(+money + 50); // 300 (number hint)
console.log(String(money)); // "250 USD" (string hint)
Object.keys: [ 'name' ]
Direct symbol read: T-800-HUNTER
300
250 USD
Symbol Properties Omitted from JSON
The Risk: `JSON.stringify({ [Symbol("key")]: "secret" })` yields `{}` because `JSON.stringify` intentionally ignores symbol keys.
The Fix: If persistence over JSON is required, map symbols to strings before serializing.
- ✓ Symbols are primitive, immutable, and 100% unique.
- ✓ `Symbol("x") === Symbol("x")` is always `false`.
- ✓ Symbol keys are invisible to `for...in` and `JSON.stringify()`.
- ✓ Use `Object.getOwnPropertySymbols(obj)` or `Reflect.ownKeys(obj)` to read them.
- ✓ Well-Known symbols (`Symbol.iterator`, `Symbol.toPrimitive`) hook into engine internals.