Symbol
Symbol is a built-in object that creates a unique identifier. Symbols are often used as object property keys to avoid naming collisions, and they serve as the foundation for well-known symbols that customize JavaScript behavior.
Creating Symbols
Create a Symbol using the Symbol() function:
const sym = Symbol();
typeof sym // "symbol"
// With a description (useful for debugging)
const namedSym = Symbol("mySymbol");
const anotherSym = Symbol("mySymbol");
namedSym === anotherSym // false - each Symbol is unique
The description is purely for debugging purposes and does not affect identity:
Symbol("test") === Symbol("test") // false
Using Symbols as Property Keys
Symbols are useful as object property keys because they’re guaranteed to be unique:
const uniqueKey = Symbol("unique");
const obj = {
[uniqueKey]: "secret value",
regularKey: "public value"
};
obj[uniqueKey] // "secret value"
obj.regularKey // "public value"
This makes Symbols ideal for:
- Defining private-like properties
- Adding properties to objects without risking name conflicts
- Creating constants that won’t clash with other code
Well-Known Symbols
JavaScript provides several built-in “well-known” Symbols that customize object behavior:
Symbol.iterator
Defines the default iterator for an object:
const iterable = {
*[Symbol.iterator]() {
yield 1;
yield 2;
yield 3;
}
};
[...iterable] // [1, 2, 3]
Symbol.toStringTag
Customizes the default string description:
const obj = {
[Symbol.toStringTag]: "MyCustomObject"
};
Object.prototype.toString.call(obj) // "[object MyCustomObject]"
Symbol.hasInstance
Allows customizing instanceof behavior:
class CustomArray {
static [Symbol.hasInstance](instance) {
return Array.isArray(instance);
}
}
[] instanceof CustomArray // true
Symbol.toPrimitive
Customizes object-to-primitive conversion:
const obj = {
value: 10,
[Symbol.toPrimitive](hint) {
return this.value;
}
};
+obj // 10
obj + 5 // 15
Getting Symbol Values
Access existing symbols using Object.getOwnPropertySymbols():
const sym = Symbol("test");
const obj = { [sym]: "value" };
Object.getOwnPropertySymbols(obj) // [Symbol(test)]
Use Symbol.for() to create or retrieve shared symbols:
const globalSym = Symbol.for("shared");
const sameSym = Symbol.for("shared");
globalSym === sameSym // true - same symbol from global registry
Symbol.keyFor(globalSym) // "shared"
Practical Examples
Creating Enum-like Values
const Direction = {
UP: Symbol("UP"),
DOWN: Symbol("DOWN"),
LEFT: Symbol("LEFT"),
RIGHT: Symbol("RIGHT")
};
function move(direction) {
switch (direction) {
case Direction.UP: return "moving up";
case Direction.DOWN: return "moving down";
// ...
}
}
move(Direction.UP) // "moving up"
Defining Private Properties
const _counter = Symbol("counter");
class Counter {
constructor() {
this[_counter] = 0;
}
increment() {
this[_counter]++;
return this[_counter];
}
}
const c = new Counter();
c.increment(); // 1
c._counter; // undefined - not directly accessible
Limitations
- Symbols as property keys are not enumerable in
for...inloops Object.keys()andObject.getOwnPropertyNames()don’t return Symbol keys- Symbols are not serialized in
JSON.stringify() - Each
Symbol()call creates a new unique value
See Also
- JavaScript Symbols Guide - Deep dive into symbols with practical examples
- Object.keys() - Get enumerable property names
- Object.getOwnPropertySymbols() - Get symbol properties from objects
- Iterators and Generators - Using Symbol.iterator for custom iteration