Symbols in JavaScript: Unique and Special Values
In JavaScript, Symbol is a new primitive type (introduced in ES6) that serves as a special and unique value, primarily used as an object key to avoid conflicts with other keys.
In this article, we will learn:
- What is a Symbol?
- How to create and use it
- Where Symbols are used
- Built-in Symbols in JavaScript
- Practical examples
What is a Symbol?
A Symbol in JavaScript is a primitive type, like number, string, or boolean. It always creates a unique value, even if the description is the same.
const sym1 = Symbol("id");
const sym2 = Symbol("id");
console.log(sym1 === sym2); // false
This means even if two Symbols are created with the same "description," they are distinct.
How to Create a Symbol
const mySymbol = Symbol(); // without a description
const namedSymbol = Symbol("userId"); // with a description (for debugging)
The description does not affect the value—it only aids debugging.
Using Symbols as Object Keys
Symbols are primarily used as keys when you want to prevent accidental overwriting or collision with other properties.
const ID = Symbol("id");
const user = {
name: "Ani",
[ID]: 12345,
};
console.log(user[ID]); // 12345
Note: If we log the entire user object, Symbol-based keys will not be visible. They are "hidden" from standard loops.
Symbols Are Hidden in for...in or Object.keys
for (let key in user) {
console.log(key); // only "name"
}
console.log(Object.keys(user)); // ["name"]
console.log(Object.getOwnPropertySymbols(user)); // [Symbol(id)]
To access Symbol-based keys, use Object.getOwnPropertySymbols().
Shared Symbols (Global Symbols)
While Symbol("id") !== Symbol("id"), you can create shared Symbols using Symbol.for().
const symA = Symbol.for("globalId");
const symB = Symbol.for("globalId");
console.log(symA === symB); // true
This ensures all Symbol.for("globalId") calls return the same value.
Built-in Symbols
JavaScript has predefined Symbols that allow customizing object behavior.
Examples include:
| Symbol | Description |
| Symbol.iterator | Used to make objects iterable (for for...of). |
| Symbol.toPrimitive | Defines how an object is converted to a primitive value. |
| Symbol.toStringTag | Customizes the output of Object.prototype.toString. |
| Symbol.hasInstance | Controls the instanceof operator. |
Example: Creating an iterable object:
const myIterable = {
*[Symbol.iterator]() {
yield 1;
yield 2;
yield 3;
},
};
for (const num of myIterable) {
console.log(num); // 1, 2, 3
}
Useful Properties
typeof returns "symbol":
typeof Symbol("test"); // "symbol"
Symbols cannot be concatenated:
const s = Symbol("id");
console.log("My symbol is " + s); // TypeError
You must explicitly convert them:
console.log("My symbol is " + s.toString());
Where Are Symbols Used?
- In applications requiring "hidden" or special properties (e.g., mimicking private fields).
- Inside modules or libraries to avoid key collisions.
- For advanced patterns like iterators, observers, or custom behaviors.