Get to know the Symbol data type of JS and its usage scenarios

Original link: https://www.iyouhun.com/post-255.html

acquainted with symbol

What is Symbol

Symbol as one of ES6’s new primitive data types, represents a unique value.

Recall the categories of primitive types ( string , number , boolean , null , undefined , symbol ).

Symbol use

Create a Symbol

 const a = Symbol() console.log(typeof a) // symbol

It should be noted that the new operator is not used when creating a value through the Symbol method, because the result of instantiation through new is an object object, not a symbol of the original type.

 const a = new Symbol() console.log(typeof a) // Symbol is not a constructor

Usually using new to construct is to get a wrapper object, and Symbol does not allow this, so if we want to get an object form of Symbol() , we can use Object() function.

 const a = Symbol() const b = Object(a) console.log(typeof b) // object

The Symbol method receives a parameter representing a description of the generated symbol value.

 const a = Symbol('a') const b = Symbol('b')

Even if the same parameter is passed in, the generated symbol values ​​are not equal, because Symbol has a unique meaning.

 const a = Symbol('foo') const b = Symbol('foo') console.log(a === b) // false

Application of Symbol

The application of Symbol actually takes advantage of the uniqueness.

as properties of the object

Have you ever thought about it, if we want to add a method or attribute to an object when we don’t know it, and we are afraid of the problem of overwriting caused by repeated key names, and at this time we need a unique key to solve this problem , so Symbol comes on the scene, it can be used as the key of the property of the object, and avoid conflicts.

 // 创建一个`Symbol` const a = Symbol() // 创建一个对象const obj = {} // 通过`obj[]`将`Symbol`作为对象的键obj[a] = 'hello world'

It is worth noting that we cannot use . to call Symbol property of the object, so we must use [] to access Symbol property

Reduce code coupling

With tens of millions of lines of code, maintenance is the most difficult. The coding is not standardized, and my colleagues cry.

When the code is littered with a lot of魔法字符, it becomes difficult even for the original developer to look back at it after a while, let alone maintain it by later developers.

If there is a Tabs switching function:

 if (type === 'basic') { return <div>basic tab</div> } if (type === 'super') { return <div>super tab</div> }

The strings basic and super in the above code are magic characters that have nothing to do with the business code, and then use Symbol to transform this code.

 const tabTypes = { basic: Symbol(), super: Symbol(), } if (type === tabTypes.basic) { return <div>basic tab</div> } if (type === tabTypes.super) { return <div>super tab</div> }

mock class private method

Classes in ES6 do not have the private keyword to declare the private methods and private variables of the class, but we can use the uniqueness of Symbol to simulate.

 const speak = Symbol() class Person { [speak]() { ... } }

Because the user cannot create an identical speak externally, this method cannot be called.

Global shared Symbol

If we want to call the same Symbol in different places, that is, the globally shared Symbol , we can use Symbol.for() method. The parameter is the description string passed in during creation. This method can traverse Symbol in the global registry . When If the same description is found, this Symbol will be called, if not found, a new Symbol will be created.

For a better understanding, please see the following example

 const a = Symbol.for('a') const b = Symbol.for('a') a === b // true

Create Symbol as above

  1. First, through Symbol.for() look for Symbol described as a in the global registry, but currently there is no qualified Symbol , so create a Symbol described as a
  2. When declaring b and using Symbol.for() to find Symbol described as a in the global registry, find and assign
  3. The result of comparing a and b is true reflects the role of Symbol.for()

Take a look at the following code

 const a = Symbol('a') const b = Symbol.for('a') a === b // false

The result turned out to be false . The difference from the above is only in the way the first Symbol is created. Let’s analyze step by step why such a result occurs.

  1. Use Symbol('a') to create directly, so the Symbol('a') is not in the global registry
  2. Use Symbol.for('a') to look for Symbol described as a in the global registry, but it is not found, so a new Symbol described as a is created in the global registry
  3. Adhering to the unique feature created by Symbol , so Symbol created by a and b is different, and the result is false

The problem came again! How do we judge whether our Symbol is in the global registry?

Symbol.keyFor() helps us solve this problem, he can query whether the Symbol corresponding to the variable name is in the global registry (created by Symbol.for ) through the variable name

 // Symbol.keyFor 方法返回一个使用Symbol.for 方法创建的symbol 值的key const a = Symbol('a') const b = Symbol.for('a') Symbol.keyFor(a) // undefined Symbol.keyFor(b) // 'a'

What is the built-in Symbol value?

The use of the above Symbol is customized by us, and JS has a built-in Symbol value. My personal understanding is: due to the uniqueness, in the object, as a unique key and corresponding to a method, when the object calls a method The method corresponding to the Symbol value will be called at some time, and we can also change the effect of the external method by changing the method corresponding to the built-in Symbol value.

In order to better understand the above paragraph, let’s take Symbol.hasInstance as an example to see what the built-in Symbol is!

 class demo { static [Symbol.hasInstance](item) { return item === '游魂博客' } } "游魂博客" instanceof demo // true

The external method corresponding to Symbol.hasInstance is that instanceof is often used to judge the type. The above code creates a demo class and rewrites Symbol.hasInstance , so its corresponding instanceof behavior will also change. Its internal mechanism is as follows: when we call instanceof method, the internal corresponding call to Symbol.hasInstance corresponds to The method is return item === '游魂博客'

See more built-in properties: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol#static_properties

Acquisition of Symbol key in obj

For this, es6 added Object.getOwnPropertySymbols method.

 let uid = Symbol('uid') let obj = { [uid]: 'uid' } console.log(Object.keys(obj)) // [] console.log(Object.getOwnPropertyNames(obj)) // [] console.log(Object.getOwnPropertySymbols(obj)) // [Symbol(uid)]

Symbol is not coercible

 let uid = Symbol('uid') uid + ''

An error will be reported here. According to the specification, he will convert the uid into a string for addition. If you really add, you can first add String(uid) and then add, but at present, it seems meaningless.

Here are just some basic usages of Symbol, please refer to the documentation for other usages: MDN

This article is transferred from: https://www.iyouhun.com/post-255.html
This site is only for collection, and the copyright belongs to the original author.