Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.
Today we will learn JavaScript’s new primitive type Symbol, we can use Symbol to create a unique value as an object attribute or value, we can also use Symbol’s well-known to modify the internal logic of JS language.
Create a Symbol
ES6 adds Symbol as the primitive data type, along with other primitive data types such as Number, Boolean, NULL, undefined, and String. Symbol has no literal form.
To create a symbol, we use the global function symbol ()
let s = Symbol('foo');
Copy the code
The Symbol() function creates a new unique value each time it is called
console.log(Symbol() = = =Symbol()); // false
Copy the code
The Symbol() function takes an optional parameter as a description to make Symbol more semantic.
Create two symbols: firstName and lastName.
let firstName = Symbol('first name'),
lastName = Symbol('last name');
Copy the code
We implicitly call symbol’s toString() method when we use console.log() to print the symbol.
console.log(firstName); // Symbol(first name)
console.log(lastName); // Symbol(last name)
Copy the code
Since symbol is a primitive value, we can use typeof to check its type. Similarly, ES6 extends the Typeof keyword to return symbol when encountering a symbol type
console.log(typeof firstName);
// symbol
Copy the code
Since it is a primitive type, it cannot be created using new
let s = new Symbol(a);// error
Copy the code
Shared symbol
To create a shared symbol, use the symbol.for () function instead of symbol ().
Symbol.for() also accepts an optional parameter as a description
let ssn = Symbol.for('ssn');
Copy the code
Symbol.for() first looks globally to see if there is a Symbol for the SSN already created, returns the Symbol already created if there is one, and creates a new Symbol if there is none.
Next, we create an identical symbol and then check that it is not the same symbol
let nz = Symbol.for('ssn');
console.log(ssn === nz); // true
Copy the code
Because the SSN symbol has been created above, the SYMBOL for the NZ variable will be the same as the symbol created above.
If you want to get the key of symbol, use the symbol.keyfor () method
console.log(Symbol.keyFor(nz)); // 'ssn'
Copy the code
Note that using symbol.keyfor () returns undefined if symbol is created through symbol ()
let systemID = Symbol('sys');
console.log(Symbol.keyFor(systemID)); // undefined
Copy the code
Symbol is futile
Use Symbol as a unique value
In code, we often use strings or numbers to represent some states, and we often face the problem of lack of semantics or repeated definition. In this case, using Symbol is the best choice. Each newly created Symbol is unique, and there will be no repetition.
In the example below, we use Symbol to represent several states of an order, rather than strings and numbers
let statuses = {
OPEN: Symbol('Placed'),
IN_PROGRESS: Symbol('In transit'),
COMPLETED: Symbol('Order Fulfilled'),
CANCELED: Symbol('Order Cancelled')};// Complete the order
task.setStatus(statuses.COMPLETED);
Copy the code
Use symbol as the object attribute
Use Symbol for the attribute name
let status = Symbol('status');
let task = {
[status]: statuses.OPEN,
description: 'Learn ES6 Symbol'
};
console.log(task);
Copy the code
Use object.keys () to get all the enumerable properties of an Object
console.log(Object.keys(task));
// ["description"]
Copy the code
Use Object. GetOwnPropertyNames () for all attributes, whether or not can be enumerated
console.log(Object.getOwnPropertyNames(task));
// ["description"]
Copy the code
To obtain Object Symbol of property, need to use new Object ES6. GetOwnPropertySymbols () method
console.log(Object.getOwnPropertySymbols(task));
//[Symbol(status)]
Copy the code
Well-known symbol
ES6 defines symbol-related attributes on the prototype chain to expose more of the language’s internal logic. Well-known symbols define functions for standard objects that were previously only visible within the language.
Symbol.hasInstance
Symbol.hasInstance is a Symbol that changes the default behavior of the instanceof operator, which is how we normally use instanceof
obj instanceof type;
Copy the code
The JavaScript then executes the symbol.hasintance method, as follows
type[Symbol.hasInstance](obj);
Copy the code
It calls the symbol.hasinstance static method of type, taking obj as an argument
class Stack {}console.log([] instanceof Stack);
// false
Copy the code
[] Array is not an instance of the Stack class, so return false.
Assuming we want the [] array to be an instance of the Stack class and return true, we can override the symbol.hasinstance method
class Stack {
static [Symbol.hasInstance](obj) {
return Array.isArray(obj); }}console.log([] instanceof Stack);
// true
Copy the code
Symbol.iterator
Symbol.iterator specifies whether the function returns an iterator of an object.
Objects with the Symbol. Iterator attribute are called iterables.
In ES6, Array, Set, Map, and String are all iterables.
ES6 provides for… The of loop, which can be used on an iterable.
var numbers = [1.2.3];
for (let num of numbers) {
console.log(num);
}
/ / 1
/ / 2
/ / 3
Copy the code
Behind the scenes, the JavaScript engine first calls the symbol.iterator method of the numbers array to get the iterator object. It then calls iterator.next() and copies the iterator object’s value property into the num variable. After 3 iterations, The done object is true, and the loop rolls out.
We can get the iterator object of an array using symbol. iterator.
var iterator = numbers[Symbol.iterator]();
console.log(iterator.next()); // Object {value: 1, done: false}
console.log(iterator.next()); // Object {value: 2, done: false}
console.log(iterator.next()); // Object {value: 3, done: false}
console.log(iterator.next()); // Object {value: undefined, done: true}
Copy the code
By default, a self-defined collection is not iterable, but we can make it iterable using symbol. iterator
class List {
constructor() {
this.elements = [];
}
add(element) {
this.elements.push(element);
return this; } * [Symbol.iterator]() {
for (let element of this.elements) {
yieldelement; }}}let chars = new List();
chars.add('A')
.add('B')
.add('C');
// Use Symbol. Iterator to implement iteration
for (let c of chars) {
console.log(c);
}
// A
// B
// C
Copy the code
Symbol.isConcatSpreadable
We can combine two arrays using the concat() method
let odd = [1.3],
even = [2.4];
let all = odd.concat(even);
console.log(all); // [1, 3, 2, 4]
Copy the code
We can also use concat() to pass in individual elements instead of arrays
let extras = all.concat(5);
console.log(extras); // [1, 3, 2, 4, 5]
Copy the code
In the example above, when we pass an array to the concat() method, the concat() method expands the array into a single element. However, it treats individual raw parameters differently, and prior to ES6, we couldn’t change this behavior.
let list = {
0: 'JavaScript'.1: 'Symbol'.length: 2
};
let message = ['Learning'].concat(list);
console.log(message); // ["Learning", Object]
Copy the code
The list object is merged into the [‘Learning’] array, but the individual elements of the list object are not merged into the array.
In concat () will list the elements in the object is added to the array of alone, we need to put the Symbol. IsConcatSpreadable attribute is added to the list object, like this
let list = {
0: 'JavaScript'.1: 'Symbol'.length: 2[Symbol.isConcatSpreadable]: true
};
let message = ['Learning'].concat(list);
console.log(message); // ["Learning", "JavaScript", "Symbol"]
Copy the code
. If the Symbol isConcatSpreadable set to false, the concat () will list the entire object merge into the array.
Symbol.toPrimitive
The symbol.toprimitive method determines the behavior of an object when it is converted to its original value.
The JavaScript engine defines the symbol.toprimitive method on the prototype of each type value.
The symbol. toPrimitive method takes a hint parameter, which is string, number, and default. The hint parameter specifies the type of return value. Hint parameters are populated by the JavaScript engine based on the context in which the object is used.
function Money(amount, currency) {
this.amount = amount;
this.currency = currency;
}
Money.prototype[Symbol.toPrimitive] = function(hint) {
var result;
switch (hint) {
case 'string':
result = this.amount + this.currency;
break;
case 'number':
result = this.amount;
break;
case 'default':
result = this.amount + this.currency;
break;
}
return result;
}
var price = new Money(10000.Renminbi);
console.log('I have' + price); // Price is 799USD
console.log(+price + 1); / / 800
console.log(String(price)); // 799USD
Copy the code
other
-
Symbol.match(regex) : A method called when the string.prototype.match () method is called to compare strings.
-
Symbol.replace(regex, replacement) : A method called when the string.prototype.replace () method is called to replace substrings of strings.
-
Symbol.search(regex) : A method called when the string.prototype.search () method is called to locate substrings in a String.
-
Symbol.species(regex) : Constructor used to create derived objects.
-
Symbol.split: a method called when the string.prototype.split () method is called to split strings.
-
Symbol. ToStringTag: a String in the call. The prototype. The toString () method is used when the String, used to create the object description.
-
Symbol.unscopables: A collection of objects that define the property names of objects that cannot be referenced by the with statement.
conclusion
Today, we learned all the ways of using Symbol, as well as some common ways in ordinary times. I hope it helps.
If this article is helpful, wechat search [xiaoshuai’s programming notes], let us progress every day