Symbols
A symbol is a special primitive data type: a value that is guaranteed to be unique. Symbols are used as keys for properties that must not accidentally clash with other keys or show up in an ordinary loop. JavaScript itself uses them to describe how objects behave, for example how for...of walks through them.
Creating a symbol
A symbol is created with the Symbol() function. Every call gives a new value equal to no other — not even to a symbol with the same description:
console.log(Symbol('id') === Symbol('id')); // falseA symbol's description
The string in parentheses is the symbol's description. It is only for debugging: it helps you tell which symbol you are looking at in the console:
const id = Symbol('id');
console.log(typeof id); // symbol
console.log(id.description); // idA symbol as a key
A symbol can be the key of an object property. When creating the object you write it in square brackets, and you access the property with brackets too:
const id = Symbol('id');
const user = { name: 'Anna', [id]: 7 };
console.log(user[id]); // 7Only code that holds the symbol itself can reach such a property. Other code will not overwrite it by mistake, even if it adds its own id property.
Hidden properties
Symbol properties do not show up in Object.keys(), the for...in loop or JSON.stringify(). That makes them handy for service data that must not be sent to the server:
const id = Symbol('id');
const user = { name: 'Anna', [id]: 7 };
console.log(Object.keys(user).join(', ')); // name
console.log(JSON.stringify(user)); // {"name":"Anna"}They are not completely hidden: Object.getOwnPropertySymbols(user) returns a list of them.
The global registry: Symbol.for
Sometimes different parts of a program need the same symbol. Symbol.for() looks for a symbol with that name in a shared registry and creates it only if it is not there yet:
const a = Symbol.for('app.id');
const b = Symbol.for('app.id');
console.log(a === b); // trueBuilt-in symbols
JavaScript has a set of built-in symbols through which an object configures its behaviour. Symbol.iterator from the previous lesson makes an object iterable, and Symbol.toPrimitive decides what the object turns into in calculations:
const price = {
amount: 12,
[Symbol.toPrimitive]() {
return this.amount;
},
};
console.log(price * 2); // 24Common mistake
Accessing a symbol property with a dot. user.id looks for an ordinary property with the string key 'id', not for the symbol stored in the id variable:
const id = Symbol('id');
const user = { [id]: 7 };
console.log(user.id); // undefined
console.log(user[id]); // 7