What are Symbols?
Symbol is a primitive data type in JavaScript. Every symbol is unique and immutable. They're often used as unique identifiers for object properties, preventing name collisions when different parts of your code need to add properties to the same object.
const sym1 = Symbol();
const sym2 = Symbol("description");
console.log(sym1 === sym2); // false — every symbol is unique
// Symbols are useful as object keys
const id = Symbol("id");
const user = {
name: "Alice",
[id]: 123, // Unique key that won't collide
};
console.log(user[id]); // 123
Well-Known Symbols
JavaScript has several built-in symbols that let you customize how objects behave. For example, Symbol.iterator makes an object iterable with for...of.
class Range {
constructor(start, end) {
this.start = start;
this.end = end;
}
[Symbol.iterator]() {
let current = this.start;
const end = this.end;
return {
next() {
if (current <= end) {
return { value: current++, done: false };
}
return { done: true };
},
};
}
}
const range = new Range(1, 5);
for (const num of range) {
console.log(num); // 1, 2, 3, 4, 5
}
Using Symbols as Property Keys
Symbol properties don't show up in for...in loops or Object.keys(). This makes them useful for "hidden" properties that won't interfere with other code.
const secret = Symbol("secret");
const obj = {
name: "visible",
[secret]: "hidden",
};
console.log(Object.keys(obj)); // ["name"]
console.log(obj[secret]); // "hidden"
// To get symbol properties:
console.log(Object.getOwnPropertySymbols(obj)); // [Symbol(secret)]
Try it Yourself →
Global Symbol Registry
You can create shared symbols using Symbol.for(). These are stored in a global registry and return the same symbol when accessed from anywhere in your code.
const sym1 = Symbol.for("shared");
const sym2 = Symbol.for("shared");
console.log(sym1 === sym2); // true — same symbol from registry
// Get the key for a global symbol
console.log(Symbol.keyFor(sym1)); // "shared"
Summary
Symbols provide unique identifiers and let you customize object behavior through well-known symbols. They're great for avoiding property name conflicts and building more powerful abstractions.