This is the 21st day of my participation in the August More Text Challenge

ES6 introduced Symbol as a non-string attribute name. To understand Symbol, you need to know that JavaScript’s basic object type is an unordered collection of properties, each of which has a name and a value. Attribute names are usually strings (prior to ES6). But in ES6 and later, Symbol can also be used for this purpose:

let strname = "string name"; // String as attribute name
let symname = Symbol("propname"); // A Symbol is used for attribute names
typeof strname // => "string": strname is a string
typeof symname // => "symbol": symname is a symbol
let o = {}; // Create an object
o[strname] = 1; // Define attributes using strings
o[symname] = 2; // Use Symbol to define attributes
o[strname] // => 1: accesses string-named attributes
o[symname] // => 2: access the named properties of Symbol
Copy the code

The Symbol type has no text syntax. Call the Symbol() function to get the Symbol value. This function never returns the same value twice, even when called with the same arguments. This means that if you call Symbol() to get the Symbol value, you can safely use that value as the attribute name to add a new attribute to the object without worrying about overwriting an existing attribute with the same name. Similarly, if you use symbolic attribute names without sharing those symbols, you can be sure that other code modules in your program won’t accidentally overwrite the attributes.

In practice, Symbol is an extension mechanism of language. When ES6 introduced for/of loops and Iterable objects, it needed to define standard methods that classes could implement to make themselves iterable. However, standardizing any particular string name for this iterator method breaks the existing code, so use the Symbol name instead. Symbol.iterator is a Symbol value that can be used as a method name to make its object iterable.

The Symbol() function takes an optional string argument and returns a unique Symbol value. If a string argument is provided, the string is included in the output of the toString() method of the symbol. Note, however, that calling Symbol() twice with the same string yields two completely different Symbol values.

let s = Symbol("sym_x");
console.log(s.toString()) // => "Symbol(sym_x)"
Copy the code

We can see if calling Symbol() twice with the same argument yields the same Symbol value

let s = Symbol('sym_x');
console.log(s.toString()) // => "Symbol(sym_x)"
let t = Symbol('sym_x');
console.log(t.toString()) // => "Symbol(sym_x)"
console.log(s === t); // false
Copy the code

ToString () is the only method of interest in symbol instances. However, there are two other symbol-related functions you should know about. Sometimes, when you use symbols, you want to keep them private to your own code so that you can ensure that the attributes don’t conflict with attributes used by other code. Other times, however, you might want to define a symbol value and share it widely with other code. For example, if you are defining an extension and you want other code to participate, such as symbol.iterator described earlier.

To meet the latter needs, JavaScript defines a global symbol registry. The symbol.for () function takes a string argument and returns the Symbol value associated with the passed string. If there is no symbol associated with the string, a new symbol is created and returned; Otherwise, an existing symbol is returned. That is, the symbol.for () function is completely different from the Symbol() function: Symbol() never returns the same value twice, but symbol.for () always returns the same value when called with the same string. The string passed to symbol.for () appears in the output of toString() that returns the Symbol, and can also be retrieved by calling symbol.keyfor () on the returned Symbol.

let s = Symbol.for("shared");
let t = Symbol.for("shared");
s === t // => true
s.toString() // => "Symbol(shared)"
Symbol.keyFor(t) // => "shared"
Copy the code