- “Symbol” value represents a unique identifier.
- Symbols are guaranteed to be unique.
- Even if we create many symbols with the same description, they are different values.
- The description is just a label that doesn’t affect anything.
- A value of this type can be created using
Symbol()
.
let id1 = Symbol();
let id2 = Symbol("id"); // id2 is a symbol with the description "id"
console.log(id1 == id2); // false
- Most values in JavaScript support implicit conversion to a string.
- Symbols are special and they don’t auto-convert.
- If we really want to show a symbol, we need to call
toString()
on it.
- That’s a “language guard” against messing up, because strings and symbols are fundamentally different and should not occasionally convert one into another.
- Symbols allow us to create “hidden” properties of an object, that no other part of code can occasionally access or overwrite.
- For instance, if we want to store an “identifier” for the object user, we can use a symbol as a key for it.
- If we want to use a symbol in an object literal, we need square brackets.
let id = Symbol("id");
let user = {
name: "John"
};
user[id] = "ID Value";
let user = {
[id]: 1000,
name: "John"
};
- Symbolic properties do not participate in
for..in
loop.
- That’s a part of the general “hiding” concept.
- In contrast,
Object.assign
copies both string and symbol properties.
- The idea is that when we clone an object or merge objects, we usually want all properties to be copied.
- We can only use strings or symbols as keys in objects.
- When other data types are used for keys, they are converted to strings.
let obj = {
1: "test" // same as "1": "test"
};
console.log(obj["1"]);
console.log(obj[1]);
Global Symbol Registry
- Usually all symbols are different, even if they have the same names but sometimes we want same-named symbols to be same entities.
- With global symbol registry, we can create symbols in and access them later.
- It guarantees that repeated accesses by the same name return exactly the same symbol.
- In order to create or read a symbol in the registry, use
Symbol.for(key)
.
- That call checks the global registry, and if there’s a symbol described as
key
, then returns it.
- Otherwise creates a new symbol
Symbol(key)
and stores it in the registry by the given key
.
- Symbols inside the registry are called global symbols.
// Read from the global registry
let id = Symbol.for("id"); // if the symbol did not exist, it is created
let idAgain = Symbol.for("id"); // Read it again
console.log(id === idAgain); // true
Symbol.keyFor
- There’s a reverse call:
Symbol.keyFor(sym)
, that returns a name by a global symbol.
let sym1 = Symbol.for("name");
let sym2 = Symbol.for("id");
console.log(Symbol.keyFor(sym1)); // name
console.log(Symbol.keyFor(sym2)); // id
- The
Symbol.keyFor
internally uses the global symbol registry to look up the key for the symbol.
- So it doesn’t work for non-global symbols.
- If the symbol is not global, it won’t be able to find it and return undefined.
console.log(Symbol.keyFor(Symbol.for("name"))); // name, global symbol
console.log(Symbol.keyFor(Symbol("name2"))); // undefined, the argument isn't a global symbol