What is Symbol?
Symbols is not an icon, nor does it mean that you can use a small picture in your code:
Nor does it refer to the grammar of other things. So, what exactly is Symbol to?
Seven types of data
When JavaScript was normalized in 1997, there were 6 types of data, until ES6, the variables in the program must be one of the following 6 data types:
Undefined
Null
Boolean
Number
String
Object
Each data type is a combination of a series of values, and the number of previous 5 data type values is limited. A Boolean type has only two values: True and false, and when assigned to a variable of a Boolean type, no new value is generated (two values that share true and false). For number and String, they have a much more value, and the standard argument is a value of 18,437,736,874,454,810,627 number types (including NAN). The number of String types is difficult to count, I thought it was (2144,115,188,075,855,872.1) ÷65,535 ... But maybe I was wrong.
The number of object values is infinite, each object is unique, and each time a page is opened, a series of objects are created.
Symbol in ES6 is also a data type, but it is not a string, it is not an object, but a new data type: The seventh type of data.
Let's look at a scene where Symbol might come in handy.
a problem that arises from a Boolean value
Sometimes it is convenient to have some data belonging to other objects in another object. For example, suppose you are writing a JS library, using the transition in CSS to make a DOM element run on the screen, you already know that you can't apply multiple transition to the same div at the same time, otherwise it will make the animation very ugly, you do have a way to solve the problem, But first you need to know if the div is already moving.
How to solve this problem?
One method is to use the API provided by the browser to detect whether an element is animated, but kill a chicken with a sledgehammer, and when you set the element to move, your library knows that the element is moving.
What you really need is a mechanism to track which elements are moving, you can save the elements that are moving in an array, and each time you want to animate an element, first check to see if the element is already in the list.
Aha, but if your array is very large, even such linear searches can have performance problems.
So what you really want to do is set a flag directly on the element:
if (element.ismoving) {
smoothanimations (element);
}
Element.ismoving = true;
if (element.ismoving) {
smoothanimations (element);
}
Element.ismoving = true;
This also has some potential problems and has to acknowledge the fact that there are other codes that may also manipulate the ODM element.
- In other code, the attributes you create are enumerated by for-in or Object.keys ();
- Some other libraries may have used the same approach (setting the same attribute on the element), which would conflict with your code and produce unpredictable results;
- Some other libraries may use the same approach in the future, which can also conflict with your code;
- The standard Committee may add a. ismoving () native method to each element, and your code will be completely out of work.
Of course, for the last three questions, you can choose a meaningless string that no one will ever use:
if (element.__$jorendorff_animation_library$please_do_not_use_this_property$ismoving__) {
smoothAnimations ( element);
}
element.__$jorendorff_animation_library$please_do_not_use_this_property$ismoving__ = true;
if (element.__$jorendorff_animation_library$please_do_not_use_this_property$ismoving__) {
smoothAnimations ( element);
}
element.__$jorendorff_animation_library$please_do_not_use_this_property$ismoving__ = true;
It seems too unreliable to see the pain in the eyes.
You can also use cryptographic algorithms to generate an almost unique string:
Get 1024 Unicode Characters of gibberish
var ismoving = Securerandom.generatename ();
...
if (element[ismoving]) {
smoothanimations (element);
}
Element[ismoving] = true;
Get 1024 Unicode Characters of gibberish
var ismoving = Securerandom.generatename ();
...
if (element[ismoving]) {
smoothanimations (element);
}
Element[ismoving] = true;
Object[name] Syntax allows us to use any string as the property name, the code works, the conflict is almost impossible, and the code looks much more beautiful.
However, this results in a bad debugging experience, and every time you use Console.log () to print out the element that contains the attribute, you see a huge garbage string, and if there is more than one of these attributes? How do you make these properties look more intuitive after each refresh with the property names changing?
Why is it so hard? We're just trying to save a little bit of a sign.
use Symbol to solve the problem
A Symbol value can be created by a program and can be a property name, without worrying about property name collisions.
var mysymbol = Symbol ();
var mysymbol = Symbol ();
Calling the symbol () method creates a new value of type symbol that is not equal to any other value.
As with numbers and strings, the value of a Symbol type can also be the property name of an object, and because it is not equal to any other value, the corresponding property does not collide:
Obj[mysymbol] = "ok!"; Guaranteed not to Collide
Console.log (Obj[mysymbol);//ok!
Obj[mysymbol] = "ok!"; Guaranteed not to Collide
Console.log (Obj[mysymbol);//ok!
Here's how to solve the problem with Symbol:
Create a unique symbol
var ismoving = symbol ("ismoving");
...
if (element[ismoving]) {
smoothanimations (element);
}
Element[ismoving] = true;
Create a unique symbol
var ismoving = symbol ("ismoving");
...
if (element[ismoving]) {
smoothanimations (element);
}
Element[ismoving] = true;
The above code needs to note several points:
- The "ismoving" string in method symbol ("Ismoving") is referred to as the description information for symbol, which is very helpful for debugging. It can be printed either through Console.log (ismoving), or by ismoving.tostring () to convert ismoving to a string, or in some error message.
- Element[ismoving] Accesses the Symbol-keyed property, which is the same as any other property except that the property name is a value of type symbol.
- As with arrays, the Symbol-keyed property cannot be passed. operator to access, you must use square brackets in the way.
- It is also very convenient to manipulate the Symbol-keyed property, and we already know how to get and set the value of Element[ismoving by the code above, and we can also use this: if (ismoving in element) or delete element[ Ismoving].
- On the other hand, the above code can only be used within the scope of the ismoving, which enables a weak encapsulation mechanism: create some Symbol within a module that only objects within that module can use without worrying about conflicting code with other modules.
Since symbol was designed to avoid conflicts, when traversing a JavaScript object, it does not enumerate the attributes built with symbol, for example, the for-in loop traverses only the attributes that are keyed as strings, Object.keys (obj) and Object.getownpropertynames (obj) is the same, but this does not mean that the attributes of Symbol as keys are not enumerable: The new method of using Object.getownpropertysymbols (obj) can be enumerated, and Reflect.ownkeys (obj) This new method can return all the strings and Symbol keys in an object. (I'll detail the new feature in reflect later in this article.) )
The designers of libraries and frameworks will find many uses for Symbol, and later we'll see that the JavaScript language itself has a wide range of applications.
What exactly is Symbol?
> typeof symbol () "
symbol"
> typeof symbol ()
"symbol"
Symbol is a completely different thing. Once created, you cannot change them, and you cannot set properties on them (if you try to do so in strict mode, you will get a typeerror). They can act as property names, and they are no different from the property names of strings.
On the other hand, each symbol is unique and is not duplicated with other symbol (that is, it is created with the same symbol description), and creating a symbol is as easy as creating an object.
The symbol in ES6 is similar to the symbol in traditional languages, such as Lisp and Ruby, but is not completely copied into JavaScript. In Lisp, all identifiers are Symbol; in JavaScript, identifiers and most attributes are still strings, and Symbol only provides an extra choice.
It is noteworthy that, unlike other types, Symbol cannot be automatically converted to a string, and a typeerror is returned when an attempt to cast a Symbol into a string is attempted.
> var sym = Symbol ("<3");
> "Your symbol is" + sym
//typeerror:can ' t convert symbol to string
> ' Your symbol ' ${sym} '
//Type Error:can ' t convert symbol to string
> var sym = symbol ("<3");
> "Your symbol is" + sym
//typeerror:can ' t convert symbol to string
> ' Your symbol ' ${sym} '
//Type Error:can ' t convert symbol to string
Such casts should be avoided and should be converted using String (SYM) or sym.tostring ().
three ways to get Symbol
- Symbol () returns a unique symbol each time it is invoked.
- Symbol.for (String) returns the corresponding symbol from the symbol registry, unlike the previous method, symbol in the symbol registry is shared. In other words, if you call Symbol.for ("Cat") three times, you will return the same Symbol. The registry is useful when different pages or different modules on the same page need to share Symbol.
- Symbol.iterator returns a predefined number of Symbol languages, each of which has a special purpose.
If you're still unsure if symbol is useful, the next thing will be interesting, because I'm going to show you the actual application of symbol.
The application of Symbol in ES6 specification
We already know that you can use Symbol to avoid code collisions. Before introducing iterator, we also resolved that the for (Var item of MyArray) was started with the call Myarray[symbol.iterator] (), and I mentioned that the method could use Myarray.iterator () to Instead, it is better to use Symbol for back-compatibility.
There are some places in ES6 that use Symbol. (These features are not yet implemented in FireFox.) )
- Make instanceof extensible. In ES6, the object instanceof constructor expression is normalized as a method of a constructor: Constructor[symbol.hasinstance] (object), which means that it is extensible.
- Eliminates conflicts between new attributes and old code.
- Supports string matching for new types. In ES5, when you call Str.match (MyObject), you first attempt to convert MyObject to a RegExp object. In ES6, you first check whether there is a myobject[symbol.match] (str) method in the MyObject that provides a custom string parsing method where all regular expressions work.
These uses are narrow, but it's hard to see the big impact of these new features just through the code in my article. The JavaScript Symbol is an improved version of __doubleunderscores in PHP and Python that standard organizations will use to add new features to the language without affecting existing code.