Symbol Types
In general, object property keys can be of two types: string and symbol. Symbols are ultimately unique identifiers. They can be created by using the factory function Symbol().
For instance:
javascript symbol
After creating a symbol, you can give it a name or a description. It is especially useful for debugging practices. Let’s check out the following example:
// id is a symbol, it's a description "id"
let id = Symbol("id");
As we have already noted, symbols are unique. Even when you create a variety of symbols with the same name, they are considered different symbols.
Remember that descriptions and names are merely labels not affecting anything.
Here is an example:
let mySymbol1 = Symbol("mySymbol");
let mySymbol2 = Symbol("mySymbol");
console.log(mySymbol1 == mySymbol2); // false
In the case above, the two symbols have the same description, but they are not equal.
It’s important to know that it’s not possible to auto-convert symbols to a string.
For example, this alert will bring an error:
let mySymbol = Symbol("mySymbol");
console.log(mySymbol); // TypeError: Cannot convert a Symbol value to a string
For showing a symbol, you need to explicitly call .toString() on it, as follows:
let mySymbol = Symbol("mySymbol");
console.log(mySymbol.toString()); // Symbol(mySymbol), now it works
For getting symbol.description property, call:
let mySymbol = Symbol("mySymbol");
console.log(mySymbol.description); // mySymbol
About “Hidden” Properties¶
With the help of symbols, you can easily create the so-called “hidden” properties of an object. It is impossible to access or overwrite other parts of the code.
In case you work with site objects belonging to third-party code, you will need to add identifiers to them. It is necessary to use a symbol key for it, as follows:
let site = { // belongs to another code
name: "Web"
};
let id = Symbol("id");
site[id] = 1;
console.log(site[id]); // we can access the data using the symbol as the key
In another case, when another script wants to have its identifier inside the site.
It might be another JavaScript library so that the scripts are unaware of one another.
So, that script may create its Symbol("id").
For instance:
// ...
let id = Symbol("id");
site[id] = "Their id value";
Symbols in a Literal¶
For using a symbol in an object literal, it is necessary to insert square brackets around it.
Just look at this example:
let id = Symbol("id");
let site = {
name: "Web",
[id]: 100 // not "id: 100"
};
This is because you need the value from the variable, id as the key but not the string “id”.
The for…in Skips Symbols¶
The for..in loop doesn’t involve symbolic properties. Here is an example:
let id = Symbol("id");
let site = {
name: "Web",
[id]: 10
};
for (let key in site) {
console.log(key); // name , no symbols
}
console.log("Direct: " + site[id]); // works the direct access by the symbol
Global Symbols¶
As we have already mentioned, symbols are unique, even if they have the same description. But, sometimes, you may need the symbols with the same name to be the same entities. For example, various parts of your application wish to access the symbol "id" which means the same property.
A global symbol registry is there to achieve that. It allows creating symbols inside of it and accessing them later. Moreover, it ensures that continuous accesses by the same name show precisely the same symbol. For reading a symbol for the global registry, you are recommended to use Symbol.for(key).
Using this call helps to check the global registry. Then, if there is a symbol, defined as key, it will be returned. Otherwise, a new symbol Symbol(key) will be created and stored in the registry by a particular key.
It is demonstrated in the example below:
// read from the global registry
let id = Symbol.for("id"); // if this the symbol did not exist, it's created
// read it again
let idAgain = Symbol.for("id")
// the same symbol
console.log(id === idAgain); // true
The symbols that are inside the registry are known as global symbols. You can use them at the time you want an application-wide symbol that has an entry everywhere in the code.
Symbol.keyFor¶
It is possible to use a reverse call for global symbols. You can do that with the help of Symbol.keyFor(sym). It will do the reverse: return a name by a global symbol.
For better understanding, check out the following example:
// get symbol by name
let sym1 = Symbol.for("siteName");
let sym2 = Symbol.for("id");
// get name by symbol
console.log(Symbol.keyFor(sym1)); // siteName
console.log(Symbol.keyFor(sym2)); // id
The Symbol.keyFor will work exclusively for global symbols. In case the symbol turns out not global, there will be no option for finding it and returning undefined. In other words, each symbol has a description property.
For example:
let globalSymbol = Symbol.for("name");
let localSymbol = Symbol("name");
console.log(Symbol.keyFor(globalSymbol)); // name, global symbol
console.log(Symbol.keyFor(localSymbol)); // undefined, not global
console.log(localSymbol.description); // name
System Symbols¶
Internally JavaScript uses a wide range of system symbols.
Here are some of them:
- Symbol.hasInstance
- Symbol.iterator
- Symbol.isConcatSpreadable
- Symbol.toPrimitive
There are many other system symbols, as well.
For instance, Symbol.toPrimitive is targeted at describing the object to primitive conversion.
Symbol.isConcatSpreadable can be described as a pretty specific symbol. It drives the behavior of Array#concat..
Summary¶
In JavaScript, symbols guarantee access level uniqueness to objects. All developers need to have a basic understanding of symbols and their use cases.
Technically, symbols are not entirely hidden. A built-in method Object.getOwnPropertySymbols(obj) will allow you to receive all the symbols. There exists another method, called Reflect.ownKeys(obj),, which is targeted at returning all the keys of an object along with symbolic ones. Anyway, most libraries, syntax constructs, and built-in functions avoid using the methods mentioned above.
0 Comments
CAN FEEDBACK
Emoji