Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use symbol in es6

2025-01-21 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

Most people do not understand the knowledge points of this article "how to use symbol in es6", so the editor summarizes the following content, detailed content, clear steps, and has a certain reference value. I hope you can get something after reading this article. Let's take a look at this "how to use symbol in es6" article.

Symbol is a new type in es6. Symbol is a new basic data type introduced in ECMAScript6 that represents unique values; values of type Symbol need to be generated using the Symbol () function.

The operating environment of this tutorial: windows7 system, javascript1.8.5 version, Dell G3 computer.

Symbol is a new data type introduced in ECMAScript6 that represents a unique value; it brings some benefits to JS, especially when it comes to object properties. But can they do something for us that strings can't do?

Before digging into Symbol, let's take a look at some JavaScript features that many developers may not know about.

Background

Generally speaking, the data types in js are divided into two types: value types and reference types.

Value types (basic types): numeric (Number), character type (String), Boolean type (Boolean), null and underfined

Reference types (classes): functions, objects, arrays, etc.

* * understanding of value types: * * mutual assignment between variables means opening up a new memory space and assigning the value of the variable to the new variable and saving it in the newly opened memory. After that, the changes in the values of the two variables do not affect each other, for example:

Var a = 10; / open up a memory space to save the value of variable a "10"; var b = a; / / open up a new memory space for variable b and assign a copy of the value of a to new memory; no matter how the values of / an and b change later, the values of each other will not be affected

Some languages, such as C #, have the concept of reference passing and value passing. JavaScript has a similar concept, which is inferred from the type of data passed. If you pass a value to a function, reassigning the value does not modify the value in the calling location. However, if you modify the reference type, the modified value will also be modified where it is called.

* * understanding of reference types: * * the mutual assignment between variables is only the exchange of pointers, instead of copying a copy of objects (normal objects, function objects, array objects) to the new variable, there is still only one object, just one more guide ~; for example:

Var a = {x: 1, y: 2}; / / need to open up memory space to save the object. The value of variable an is an address that points to the space where the object is saved; var b = a; / / assign the guiding address of a to b instead of copying one to the object and opening a new memory space to save it. / / at this time, the properties of the object are modified through a, and the properties of the object have been changed when the properties are viewed through b

The value type (except for the mysterious NaN value) will always be exactly equal to another value type with the same value, as follows:

Const first = "abc" + "def"; const second = "ab" + "cd" + "ef"; console.log (first = second); / / true

But reference types with exactly the same structure are not equal:

Const obj1 = {name: "Intrinsic"}; const obj2 = {name: "Intrinsic"}; console.log (obj1 = obj2); / / false//, however, their .name attribute is the basic type: console.log (obj1.name = obj2.name); / / true

Objects play an important role in the JavaScript language, and they are used everywhere. Objects are usually used as collections of key / value pairs, however, there is a big limitation in using them in this way: before symbol, the object key could only be a string, and if you try to use a non-string value as the object's key, the value will be cast to a string, as follows:

Const obj = {}; obj.foo = 'foo';obj [' bar'] = 'bar';obj [2] = 2 bar', obj [{}] =' someobj';console.log (obj); / / {'2trees: 2, foo:' foo', bar: 'bar',' [object Object]': 'someobj'} what is Symbol

The Symbol () function returns a value of type symbol, which has static properties and static methods. Its static properties expose several built-in member objects; its static methods expose the global symbol registration, similar to the built-in object class, but it is incomplete as a constructor because it does not support the syntax: "new Symbol ()". So the values generated using Symbol are not equal:

Const S1 = Symbol (); const S2 = Symbol (); console.log (S1 = = S2); / / false

When instantiating symbol, there is an optional first parameter for which you can choose to provide a string. This value is intended for debugging code, otherwise it will not really affect symbol itself.

Const S1 = Symbol ("debug"); const str = "debug"; const S2 = Symbol ("xxyy"); console.log (S1 = str); / / falseconsole.log (S1 = S2); / / falseconsole.log (S1); / / Symbol (debug) symbol as object attribute

Symbol has another important use. They can be used as keys in objects, as follows:

Const obj = {}; const sym = Symbol (); obj [sym] = "foo"; obj.bar = "bar"; console.log (obj); / / {bar: 'bar'} console.log (sym in obj); / / trueconsole.log (objsym]); / / fooconsole.log (Object.keys (obj)); / / [' bar']

At first glance, it looks like you can use symbol to create private properties on objects. Many other programming languages have their own private properties in their classes, and the omission of private attributes has always been seen as a drawback of JavaScript.

Unfortunately, code that interacts with this object can still access properties whose key is symbol. This is even possible when the calling code cannot access the symbol itself. For example, the Reflect.ownKeys () method can get a list of all keys on an object, including strings and symbol:

Function tryToAddPrivate (o) {o [Symbol ("Pseudo Private")] = 42;} const obj = {prop: "hello"}; tryToAddPrivate (obj); console.log (Reflect.ownKeys (obj)); / / ['prop', Symbol (Pseudo Private)] console.log (obj [Reflect.ownKeys (obj) [1]]); / 42

Note: some work is currently being done to address the issue of adding private attributes to classes in JavaScript. The name of this feature is called a private field, and while this will not benefit all objects, it will benefit the objects of the class instance. Private fields are available starting with Chrome 74.

Prevent attribute name conflicts

Symbols may not directly benefit from JavaScript providing private properties for objects. However, they are useful for another reason. They are useful when different libraries want to add attributes to objects without the risk of name conflicts.

It's a bit difficult for Symbol to provide private properties for JavaScrit objects, but Symbol has the added benefit of avoiding the risk of naming conflicts when different libraries add attributes to objects.

Consider a situation where two different libraries want to add basic data to an object, and maybe they both want to set some kind of identifier on the object. By simply using id as the key, there is a huge risk that multiple libraries will use the same key.

Function lib1tag (obj) {obj.id = 42;} function lib2tag (obj) {obj.id = 369;}

By using Symbol, each library can generate the required Symbol when instantiated. Then use the value of the generated Symbol as the property of the object:

Const library1property = Symbol ("lib1"); function lib1tag (obj) {obj [library1property] = 42;} const library2property = Symbol ("lib2"); function lib2tag (obj) {obj [library2property] = 369;}

For this reason, Symbol does seem to be good for JavaScript.

However, you might ask, why can't each library simply generate random strings or use namespaces when instantiating?

Const library1property = uuid (); / / random approachfunction lib1tag (obj) {obj [library1property] = 42;} const library2property = "LIB2-NAMESPACE-id"; / / namespaced approachfunction lib2tag (obj) {obj [library2property] = 369;}

This approach is correct, and it is actually very similar to Symbol's approach, and there is no risk of conflict unless the two libraries choose to use the same property name.

At this point, smart readers will point out that the two methods are not exactly the same. We still have a drawback with property names with unique names: their keys are very easy to find, especially when running code to iterate over keys or serialize objects. Consider the following example:

Const library2property = "LIB2-NAMESPACE-id"; / / namespacedfunction lib2tag (obj) {obj [library2property] = 369;} const user = {name: "Thomas Hunter II", age: 32}; lib2tag (user); JSON.stringify (user); / /'{"name": "Thomas Hunter II", "age": 32, "LIB2-NAMESPACE-id": 369}'

If we use Symbol for the object's property name, the JSON output will not contain its value. Why is that? Although JavaScript has support for Symbol, this does not mean that the JSON specification has changed! JSON only allows strings as keys, and JavaScript does not attempt to represent the Symbol property in the final JSON payload.

Const library2property = "f468c902-26ed-4b2e-81d6-5775ae7eec5d"; / / namespaced approachfunction lib2tag (obj) {Object.defineProperty (obj, library2property, {enumerable: false, value: 369});} const user = {name: "Thomas Hunter II", age: 32}; lib2tag (user); console.log (user) / / {name: "Thomas Hunter II", age: 32, f468c902-26ed-4b2e-81d6-5775ae7eec5d: 369} console.log (JSON.stringify (user)); / / {"name": "Thomas Hunter II", "age": 32} console.log (user [library2 property]); / / 369

A string key that is "hidden" by setting the enumerable property to false behaves very similar to the Symbol key. They are not visible through the Object.keys () traversal, but can be displayed through Reflect.ownKeys (), as shown in the following example:

Const obj = {}; obj [Symbol ()] = 1 Object.keys Object.defineProperty (obj, "foo", {enumberable: false, value: 2}); console.log (Object.keys (obj)); / / [] console.log (Reflect.ownKeys (obj)); / / ['foo', Symbol ()] console.log (JSON.stringify (obj)); / / {}

At this point, we almost recreated Symbol. Both hidden string properties and Symbol are hidden from the serializer. Both of these properties can be read using the Reflect.ownKeys () method, so they are not actually private. If we use some kind of namespace / random value for the string version of the attribute name, we eliminate the risk of accidental name conflicts among multiple libraries.

However, there is still a slight difference. Because strings are immutable and Symbol is always guaranteed to be unique, it is still possible to generate string combinations that cause conflicts. Mathematically, this means that Symbol does provide benefits that we can't get from strings.

In Node.js, when you check an object (for example, using console.log ()), if you encounter a method on an object named inspect, the function is called and the content is printed. As you can imagine, this kind of behavior is not what everyone expects, and methods usually named inspect often conflict with user-created objects.

Symbol is now available to implement this function, and can be used in equire ('util'). Inspect.custom. The inspect method is deprecated in Node.js v10, completely ignored in v1, and no one now accidentally changes the behavior of the check.

Simulate private properties

Here is an interesting method that we can use to simulate private properties on objects. This approach will take advantage of another JavaScript feature: proxy (proxy). The agent essentially encapsulates an object and allows us to interfere with various operations with that object.

Proxies provide a number of ways to intercept operations performed on objects. We can use a proxy to describe the properties available on our object, in which case we will make a proxy that hides two of our known hidden properties, one is the string _ favColor, and the other is the S ymbol assigned to favBook:

Let proxy; {const favBook = Symbol ("fav book"); const obj = {name: "Thomas Hunter II", age: 32, _ favColor: "blue", [favBook]: "Metro 2033", [Symbol ("visible")]: "foo"}; const handler = {ownKeys: target = > {const reportedKeys = [] Const actualKeys = Reflect.ownKeys (target); for (const key of actualKeys) {if (key = favBook | | key = = "_ favColor") {continue;} reportedKeys.push (key);} return reportedKeys;}}; proxy = new Proxy (obj, handler) } console.log (Object.keys (proxy)); / ['name',' age'] console.log (Reflect.ownKeys (proxy)); / / ['name',' age', Symbol (visible)] console.log (Object.getOwnPropertyNames (proxy)); / / ['name',' age'] console.log (Object.getOwnPropertySymbols (proxy)); / / [Symbol (visible)] console.log (proxy._favColor); / / 'blue'

Using the _ favColor string is simple: just read the source code of the library. In addition, use brute force to find dynamic keys (such as the previous uuid example). However, without a direct reference to Symbol, no one can access the 'Metro 2033' value from the proxy object.

Node.js warning: there is a feature in Node.js that destroys the privacy of agents. This feature does not exist in the JavaScript language itself and does not apply to other situations, such as Web browsers. It allows access to the underlying object when a proxy is given. The following is an example of using this feature to break the above example of private properties:

Const [originalObject] = process.binding ("util") .getProxydetails (proxy); const allKeys = Reflect.ownKeys (originalObject); console.log (allKeys [3]); / / Symbol (fav book)

Now we need to modify the global Reflect objects or modify the util process bindings to prevent them from being used in specific Node.js instances. But this is a terrible rabbit hole.

The above is about the content of this article on "how to use symbol in es6". I believe we all have a certain understanding. I hope the content shared by the editor will be helpful to you. If you want to know more about the relevant knowledge, please follow the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report