Symbol Types
JavaScript Symbol Types (JavaScript符号类型)
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
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: "w3cdoc"
};
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. (它可能是另一个JavaScript库,这样脚本就不会相互了解。)
So, that script may create its Symbol(“id”). (因此,该脚本可以创建其符号( “id” )。)
For instance:
// ...
let id = Symbol("id");
site[id] = "Their id value";
Symbols in a Literal
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: "w3cdoc",
[id]: 100 // not "id: 100"
};
console.log(site[id]);
This is because you need the value from the variable, id as the key but not the string “id”. (这是因为您需要变量的值, id作为键,而不是字符串“id”。)
The for…in Skips Symbols
The for…in Skips Symbols (For… in Skips符号)
The for..in loop doesn’t involve symbolic properties. Here is an example:
let id = Symbol("id");
let site = {
name: "w3cdoc",
[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
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. (正如我们已经提到的,符号是独一无二的,即使它们具有相同的描述。但是,有时您可能需要具有相同名称的符号是相同的实体。例如,应用程序的各个部分希望访问符号“id” ,这意味着相同的属性。)
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). (全球符号注册系统可以实现这一目标。它允许在其中创建符号,并在以后访问它们。此外,它确保同一名称的连续访问显示完全相同的符号。要读取全局注册表的符号,建议使用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
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. (Symbol.keyFor将专门用于全局符号。如果该符号不是全局的,将没有查找它并返回undefined的选项。换句话说,每个符号都有一个描述属性。)
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
System Symbols (系统符号)
Internally JavaScript uses a wide range of system symbols. (在内部, JavaScript使用各种系统符号。)
Here are some of them:
Symbol.hasInstance Symbol.iterator Symbol.isConcatSpreadable Symbol.toPrimitive (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.toPrimitive旨在将对象描述为原始转换。)
Symbol.isConcatSpreadable can be described as a pretty specific symbol. It drives the behavior of Array#concat..
Summary
Summary (概要)
In JavaScript, symbols guarantee access level uniqueness to objects. All developers need to have a basic understanding of symbols and their use cases. (在JavaScript中,符号保证了对象的访问级别唯一性。所有开发人员都需要对符号及其用例有基本的了解。)
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. (从技术上讲,符号并不是完全隐藏的。内置方法Object.getOwnPropertySymbols (obj)将允许您接收所有符号。还有另一种方法,称为Reflect.ownKeys (obj) ,其目标是返回对象的所有键以及符号键。无论如何,大多数库、语法构造和内置函数都避免使用上述方法。)