Symbol
Symbol is one of JavaScript's primitive types.
It was introduced in ES6, also called ECMAScript 2015.
Symbols are more advanced than strings, numbers, and booleans, but the core idea is simple:
A symbol is a unique value.
Even if two symbols look similar, they are not the same.
What Is a Symbol?
A symbol is a unique and immutable primitive value.
You create a symbol with the Symbol() function.
const id = Symbol();
console.log(typeof id); // symbolDo not use new with Symbol.
This is correct:
const id = Symbol();This is not correct:
const id = new Symbol(); // ErrorSymbol creates a primitive value, not a normal object instance.
Symbol Descriptions
You can pass a description to Symbol().
const userId = Symbol("user_id");
console.log(userId); // Symbol(user_id)The description is mainly for debugging. It helps you recognize the symbol when logging it.
The description does not control equality.
const id1 = Symbol("id");
const id2 = Symbol("id");
console.log(id1 === id2); // falseEven though both descriptions are "id", the symbols are different.
This is the most important rule:
Every call to Symbol() creates a new unique symbol.
Why Symbols Exist
Symbols are useful when you need a property key that will not accidentally conflict with another property key.
Imagine this object:
const user = {
id: 123,
name: "Asha"
};If another part of the code also uses id, it can overwrite the existing value:
user.id = "session-999";
console.log(user.id); // session-999That may not be what you wanted.
Symbols help avoid this kind of collision.
Symbols as Object Keys
Symbols can be used as object property keys.
const USER_ID = Symbol("id");
const SESSION_ID = Symbol("id");
const user = {
name: "Asha",
[USER_ID]: 12345,
[SESSION_ID]: "session-999"
};
console.log(user.name); // Asha
console.log(user[USER_ID]); // 12345
console.log(user[SESSION_ID]); // session-999Both symbols have the description "id", but they are unique keys.
There is no collision.
Bracket Notation Is Required
When using a symbol as an object key, use bracket notation.
const ID = Symbol("id");
const user = {
[ID]: 123
};
console.log(user[ID]); // 123Dot notation does not work for symbol variables.
console.log(user.ID); // undefineduser.ID looks for a string key named "ID", not the symbol stored in the variable ID.
Symbols Are Hidden from Common Iteration
Symbol keys are not included in many common object operations.
const secret = Symbol("secret");
const user = {
name: "Asha",
[secret]: "hidden value"
};
console.log(Object.keys(user)); // ["name"]Object.keys() returns string keys, not symbol keys.
for...in also skips symbol keys:
for (const key in user) {
console.log(key); // name
}JSON.stringify() ignores symbol-keyed properties:
console.log(JSON.stringify(user)); // {"name":"Asha"}This does not make symbols fully private or secure. It only means they are skipped by common enumeration tools.
Getting Symbol Keys
If you need to find symbol keys on an object, use Object.getOwnPropertySymbols().
const secret = Symbol("secret");
const user = {
name: "Asha",
[secret]: "hidden value"
};
const symbols = Object.getOwnPropertySymbols(user);
console.log(symbols); // [Symbol(secret)]
console.log(user[symbols[0]]); // hidden valueSo symbol properties are hidden from normal iteration, but they are still accessible.
The Global Symbol Registry
Normally, every Symbol() call creates a new symbol.
const a = Symbol("app_id");
const b = Symbol("app_id");
console.log(a === b); // falseSometimes you want different parts of an application to share the same symbol. For that, JavaScript provides the global symbol registry.
Use Symbol.for().
const id1 = Symbol.for("app_id");
const id2 = Symbol.for("app_id");
console.log(id1 === id2); // trueHow it works:
Symbol.for("app_id")checks the global registry.- If a symbol already exists for that key, it returns the existing symbol.
- If not, it creates one and stores it in the registry.
You can get the registry key with Symbol.keyFor().
const appId = Symbol.for("app_id");
console.log(Symbol.keyFor(appId)); // app_idSymbol.keyFor() only works with symbols from the global registry.
const localId = Symbol("local_id");
console.log(Symbol.keyFor(localId)); // undefinedSymbol() vs Symbol.for()
| Feature | Symbol() |
Symbol.for() |
|---|---|---|
| Creates a unique symbol every time | Yes | No |
| Uses the global registry | No | Yes |
| Same key can return same symbol | No | Yes |
| Best for | Private-ish unique keys | Shared symbols across code |
Use Symbol() when you want guaranteed uniqueness.
Use Symbol.for() when you intentionally want shared access to the same symbol.
Well-Known Symbols
JavaScript has built-in symbols called well-known symbols.
They let you customize some built-in language behavior.
One common example is Symbol.iterator.
Arrays and strings can be used in for...of loops because they have iterator behavior.
const text = "JS";
for (const character of text) {
console.log(character);
}Under the hood, JavaScript uses Symbol.iterator to know how to loop over the value.
You do not need to master well-known symbols yet. For now, just know that symbols are also used internally by JavaScript itself.
When Should Beginners Use Symbols?
As a beginner, you will not use symbols every day.
Most beginner code uses:
- strings
- numbers
- booleans
- null and undefined
- objects and arrays
Symbols become useful when you are:
- Building libraries
- Avoiding property name collisions
- Working with advanced object behavior
- Learning JavaScript internals
Summary
Symbol is a primitive type used to create unique values.
Remember:
Symbol()creates a new unique symbol every time.- Symbol descriptions are for debugging and do not affect uniqueness.
- Symbols can be used as object property keys.
- Symbol keys require bracket notation.
- Symbol-keyed properties are skipped by
Object.keys(),for...in, andJSON.stringify(). - Use
Object.getOwnPropertySymbols()to retrieve symbol keys. - Use
Symbol.for()when you intentionally want a shared symbol from the global registry. - JavaScript also has well-known symbols such as
Symbol.iterator.
Next, you will learn about bigint, JavaScript's primitive type for very large whole numbers.