Home  >  Article  >  Web Front-end  >  Detailed explanation of Symbol type in Javascript

Detailed explanation of Symbol type in Javascript

黄舟
黄舟Original
2017-08-08 14:06:002811browse


Detailed explanation of Symbol type in Javascript

According to the specification, the object attribute key can only be string type or symbol type, not number or boolean, only string and There are two types of symbols.
We generally compare attribute strings, now let’s look at the advantages that the symbols type brings to us.

Symbols

The "Symbol" value represents a unique identifier using the given name. Values ​​of this type can be created like this: Symbol(name):

// id is a symbol with the name "id"
let id = Symbol("id");

Symbols ensure uniqueness and will produce different values ​​even if we use the same name. For example, here are two symbols with the same name, both of which are not equal:

let id1 = Symbol("id");
let id2 = Symbol("id");

alert(id1 == id2); // false

If you are familiar with Ruby or other languages ​​​​and there are the same types of symbols, don't be misled, Javascript symbols are different.

Hidden Properties

symbol allows the creation of hidden properties of an object so that other code cannot accidentally access or overwrite them.
For example, if we want to store the "identifier" of the object user, we can create a symbol of id:
Let user = { name: “John” };
Let id = Symbol("id");

user[id] = "ID Value";
alert( user[id] ); // we can access the data using the symbol as the key

Now let's imagine that another script wants to add its own "id" attribute to the user object for its own purpose. It may be another Javascript library, so they don't know each other at all.
No problem, you can create your own Symbol("id").

The code is as follows:

// ...
let id = Symbol("id");

user[id] = "Their id value";

There is no conflict because the symbols are always different, even with the same name. Note that if we use the string "id" instead of symbol to achieve the same purpose, there will be a conflict:

let user = { name: "John" };

// our script uses "id" property
user.id = "ID Value";

// ...if later another script the uses "id" for its purposes...

user.id = "Their id value"
// boom! overwritten! it did not mean to harm the colleague, but did it!

Using symbol for literals

If we use symbol in a literal object, we need Use square brackets:

let id = Symbol("id");

let user = {
  name: "John",
  [id]: 123 // not just "id: 123"
};

because we need the symbol variable value named "id", not the string "id".

Symbol is ignored by for...in

The symbol attribute does not participate in the for..in loop, for example:

let id = Symbol("id");
let user = {
  name: "John",
  age: 30,
  [id]: 123
};

for(let key in user) alert(key); // name, age (no symbols)

// the direct access by the symbol works
alert( "Direct: " + user[id] );

At this time, part of the concept is generally hidden, if other scripts or libraries , nor is it expected to access the symbol property.
In contrast, Object.assign copies both character attributes and symbol attributes.

let id = Symbol("id");
let user = {
  [id]: 123
};

let clone = Object.assign({}, user);

alert( clone[id] ); // 123

There is no contradiction between the two. This is how the specification is designed. The idea is that when we clone or merge objects, we usually want the symbol attribute to be copied as well.

Other types of attribute keys are forced to be converted to strings:

The keys in the object can only use strings or symbols, and other types are forced to be converted to strings.

let obj = {
  0: "test" // same as "0": "test"
}

// both alerts access the same property (the number 0 is converted to string "0")
alert( obj["0"] ); // test
alert( obj[0] ); // test (same property)

Global symbol

Usually, all symbols are different, but sometimes we want the symbols of the same noun to be the same. For example, if we want to access the symbol with the noun "id" in different parts of the application, of course it needs to be the same.
This can be achieved through global symbol registration. We can create them first and then access them, and ensure that the same symbol is obtained through repeated access with the same noun.

Create or read in registration, the usage syntax is: symbol.for(name), example:

// read from the global registry
let name = Symbol.for("name"); // if the symbol did not exist, it is created

// read it again
let nameAgain = Symbol.for("name");

// the same symbol
alert( name === nameAgain ); // true

The symbol in registration is called global symbol, if We have application-wide symbols that are accessible to all code and can use global symbols.

Other programming languages, like Ruby, each noun has a single symbol. In JavaScript, we know that it is the global symbol.

Symbol.keyFor

For global symbols, there is not only Symbol.for(name), which returns the symbol according to the name, but also the opposite call: Symbol.keyFor (name), the function is opposite: return the name according to the global symbol.
Example:

let sym = Symbol.for("name");
let sym2 = Symbol.for("id");

// get name from symbol
alert( Symbol.keyFor(sym) ); // name
alert( Symbol.keyFor(sym2) ); // id

Internal implementation of Symbol.keyfor uses global symbol registration and searches for symbol names based on symbol.
So it has no effect on non-global symbols. If it is not a global symbol, it will not be found and undefined will be returned.

Example:

alert( Symbol.keyFor(Symbol.for("name")) ); // name, global symbol

alert( Symbol.keyFor(Symbol("name2")) ); // undefined, non-global symbol

Non-global symbol, the name is only used for debugging purposes.

System symbol

There are many system symbols inside Javascript, and we can use them to adjust various aspects of the object.
Here are some commonly used symbols:

  • Symbol.hasInstance

  • Symbol.isConcatSpreadable

  • Symbol.iterator

  • Symbol.toPrimitive

Example: Symbol.toPrimitive is used to describe objects when converting them to basic types. If you continue to study Javascript in depth, you will gradually become familiar with the others.

Summary

  • symbol is a basic type that implements unique identification

  • by calling symbol(name)Create symbol

  • We create a field that can only be accessed by people who know the corresponding symbol. It is very useful to use symbol

  • symbol will not appear In the for..in result

  • symbol created using symbol(name) is always different, even if the name is the same. If you want symbols with the same name to be equal, use global registration

  • symbol.for(name) to return a global symbol with a given name, and multiple calls to return the same symbol

  • Javascript has system symbols, accessed through Symbol.*. We can use them to modify some built-in behaviors.

Technically, symbols are not 100% hidden. There is a built-in method Object.getOwnPropertySymbols(obj) to get all symbols.
There is also a methodReflect.ownKeys(obj)Returns all keys of the object, including symbol.

So it’s not really hidden. But most library built-in methods and syntax constructs follow a common convention that they are hidden, and if someone explicitly calls the above method, he may fully understand what he is doing.

The above is the detailed content of Detailed explanation of Symbol type in Javascript. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn