In-depth understanding of ES6--symbols and symbol properties

Main knowledge points: creating symbolic values, using symbolic values, sharing symbolic values, and converting symbolic values. Retrieve symbol value properties as well as well-known symbols

Knowledge Points of Symbols and Symbol Properties

1. Symbol Basics

1.1 Creating symbolic values

In addition to JS's existing primitives (string, numeric, boolean, nulland undefined), ES6 introduces a new primitive: symbol ( Symbol). Symbols were originally designed to create private members of objects, and this is a long-awaited feature of JS developers. Before symbols, having strings as property names resulted in properties being easily accessible regardless of naming conventions. And "private names" means that developers can create property names that are not of type string, thus preventing the use of conventional means to probe these names.

Create symbolic value

let firstName = Symbol('first Name');
let person = {};
person[firstName] = 'hello world';
console.log(person[firstName]); //hello world
console.log(firstName); //Symbol(first Name)

This code creates a firstNamevariable as persona property of the object, and uses the symbol value every time the property is accessed. SymbolThe function can also accept an additional parameter describing the symbol value, which cannot be used to access the corresponding property, but can be used for debugging. The description of the symbol is stored in the internal [[Description]]property toString(), which is read when the symbol's method is called explicitly or implicitly. In this example, console.log()the firstNamevariable toString(), so the description is output to the log. Also there is no way to directly access [[Description]]properties .

1.2 Using symbolic values

Symbolic values ​​can be used wherever computed property names are used, such as in object literals as object properties, and in Object.defineProperty()methods or Object.defineProperties()methods.

1.3 Shared Symbol Values

If you want to share the same symbol value in different code, you should use Symbol.for()method instead of Symbol()method. Symbol.for()The method only accepts a single string type parameter as the identifier of the target symbol value, and this parameter will also become the description information of the symbol.

//共享符号值

let uid = Symbol.for('uid');
let person = {};
person[uid] = 'hello';

let id = Symbol.for('uid');
let car = {};
car[id] = '88888888';

console.log(uid===id); //true

Symbol.for()The method first searches the global symbol registry to see if there is a "uidsymbol value with the key "". If so, the method returns the existing symbol value; otherwise, it creates a new symbol value and uses that key It records it in the global symbol registry, and then returns the new symbol value. This means that subsequent calls to the Symbol.for()method will return the same symbol value.

You can also use the Symbol.keyFor()method to retrieve the corresponding key value based on the symbol value in the global symbol registry :

console.log(Symbol.keyFor(uid)); //uid
console.log(Symbol.keyFor(id)); //uid

1.4 Conversion of symbolic values

Type conversion is an important part of the JS language, and it is very flexible to convert one data type to another. However, symbolic types are very inflexible when it comes to conversions, because other types lack reasonable equivalence to symbolic values, especially symbolic values ​​that cannot be converted to string values ​​or numeric values , and are considered equivalent in logical operators true.

For example, you can use the String() method to get the description of a symbol value, but if you use the symbol value to concatenate a string, an error will be reported:

console.log(String(uid));//Symbol(uid)
console.log(uid+""); //Uncaught TypeError: Cannot convert a Symbol value to a string

1.5 Retrieving Symbol Properties

Object.keys()The and Object.getOwnPropertyNames()method can retrieve all property names of an object, the former returns all enumerable property names , while the latter returns all property names , whether enumerable or not, however neither can return properties of symbol type . Therefore, the new Object.getOwnPropertySymbols()method to allow you to retrieve the symbolic type properties of an object.

let uid = Symbol.for('uid');
let person = {};
person[uid] = 'hello';

let symbols = Object.getOwnPropertySymbols(person);
console.log(symbols.length); //1
console.log(symbols[0]); //Symbol(uid)

2. Well-known symbols

ES6 defines "well-known symbols" to represent some public behaviors in JS, which were previously considered to be only internal operations, but in ES6, well-known symbols are used to expose internal methods, providing more convenient invocation of this common a way of method. Each well-known symbol corresponds to a property of the global Symbolobject , eg Symbol.create.

Well-known symbols are:

  • Symbol.hasInstance : a method used by the instanceof operator to determine the inheritance relationship of objects;
  • Symbol.isConcatSpreadable : a boolean value indicating whether to flatten the elements of the collection when the collection object is passed as a parameter to the Array.prototype.concat() method;
  • Symbol.iterator : a method that returns an iterator;
  • Symbol.match : a method used by the String.prototype.match() function to compare strings;
  • Symbol.replace : a method used by the String.prototype.replace() function to replace substrings;
  • Symbol.search : a method used by the String.prototype.search() function to locate subcharacters;
  • Symbol.species : Constructor for generating derived objects;
  • Symbol.split : a method used by the String.prototype.split() function to split strings;
  • Symbol.toPrimitive : A method that returns the basic type value corresponding to the object;
  • Symbol.toStringTag : a method used by the String.prototype.toString() function to create object description information;
  • Symbol.unscopables : an object whose properties indicate which property names are not allowed to be included in a with statement;

2.1 Symbol.hasInstance property

Each function has a Symbol.hasInstanceproperty that determines whether the specified object is an instance of this function. This method is defined Function.prototypeon , so all functions inherit the instanceofdefault behavior when faced with the operator. Symbol.hasInstanceThe property itself is non-writable, non-configurable, and non-enumerable, thus guaranteeing that it cannot be overridden by mistake.

Symbol.hasInstanceThe method only accepts a single parameter, the value that needs to be checked. If the value is an instance of this function, the method returnstrue

obj instanceof Array
//等价于
Array[Symbol.hasInstance](obj)

2.2 Symbol.isConcatSpreadable property

Symbol.isConcatSpreadableAttribute is a boolean type attribute, which represents lengthan array-like object with a length attribute and a key of numerical type. When the concat()method , the value corresponding to the numerical key is separated into separate items, which are added to the back of the array to complete the array. stitching.

It only appears on objects of a certain type and is used to indicate concat()how the object should behave when passed as a parameter, effectively changing the default behavior of the object. You can use it to define any type of object that behaves like an array when participating in concat()a call .

//Symbol.isConcatSpreadable属性

let collection = {
	0:'hello',
	1:'world',
	length:2,
	[Symbol.isConcatSpreadable]:true
}

let arr = ['es6'].concat(collection);
console.log(arr); //["es6", "hello", "world"]

2.3 Symbol.match 、 Symbol.replace 、 Symbol.search与Symbol.split

In JS, strings are closely related to regular expressions, especially strings have several methods that can accept regular expressions as arguments:

  • match(regex) : Determine whether the specified string matches a regular expression;
  • replace(regex, replacement) : Replace the matching result of the regular expression;
  • search(regex) : locate the matching result of the regular expression within the string;
  • split(regex) : Split a string into an array using a regular expression

ES6 defines 4 symbols and corresponding methods, you can pass a regular expression as the first parameter of the method corresponding to the string, Symbol.matchcorresponding match()method , Symbol.replacecorresponding replace(), Symbol.searchcorresponding search(), Symbol.splitcorresponding split(). These symbolic properties are defined RegExp.prototypeon as default implementations for use by the corresponding string methods.

2.4 Symbol.toPrimitive

JS often tries to do implicit conversions when using certain operators in order to convert objects to primitive values. For example, when you use the equality ( ==) operator to compare a string to an object, the object is converted to a primitive value before the comparison. Converting to a basic type value was previously an internal operation, but ES6 Symbol.toPrimitiveexposes it through the attribute so that the corresponding method can be modified.

function Temperature(degrees) {
	this.degrees = degrees;
} 
Temperature.prototype[Symbol.toPrimitive] = function(hint) {
	switch (hint) {
		case "string":
			return this.degrees + "\u00b0"; // 温度符号
		case "number":
			return this.degrees;
		case "default":
			return this.degrees + " degrees";
	}
};
let freezing = new Temperature(32);
console.log(freezing + "!"); // "32 degrees!"
console.log(freezing / 2); // 16
console.log(String(freezing)); // "32°"

This script defines a Temperature constructor and overrides the Symbol.toPrimitivemethods on its prototype. The return value will vary according to the method's prompt parameters, which can be in string mode, numeric mode or default mode, and the prompt parameters will be automatically filled in by the JS engine when called. In string mode, the temperature returned by the Temperature function will be accompanied by the Unicode temperature symbol; in numeric mode, only the temperature value will be returned; in default mode, the returned temperature will be accompanied by the string "degrees" .

2.5 Symbol.toStringTag

Symbol.toStringTagES6 redefines related behavior by , which represents a property of all objects that defines Object.prototype.toString.call()what value should be returned when called. For arrays, Symbol.toStringTagthe "Array" value is stored in the property, so the return value of this function is also "Array".

function Person(name){
	this.name = name;
}


Person.prototype[Symbol.toStringTag] = 'person';
let person = new Person('hello world');
console.log(person.toString()); //[object person]

2.6 Symbol.unscopables

Symbol.unscopablesThe notation Array.prototypeis used on to specify which properties are not allowed withto be bound within the statement. Symbol.unscopablesA property is an object whose key, when provided, is withan identifier for ignoring statement bindings, and a key value of truerepresenting masked binding. The following are the default values ​​for the Symbol.unscopablesproperty :

// 默认内置在 ES6 中
Array.prototype[Symbol.unscopables] = Object.assign(Object.create(null), {
	copyWithin: true,
	entries: true,
	fill: true,
	find: true,
	findIndex: true,
	keys: true,
	values: true
});

3. Summary

  1. Although properties of symbol types are not truly private, they are difficult to inadvertently modify, so they are suitable where protection is required from the developer;
  2. Provides descriptive information for symbols to make it easier to identify their values. When you need to share symbols in different code fragments, you can use S ymbol.for()to share symbols in the global symbol registry;
  3. Object.keys()or Object.getOwnPropertyNames()does not return a symbolic value, so ES6 added a Object.getOwnPropertySymbols()method that allows retrieving object properties of symbolic types. At the same time, you can still use Object.defineProperty()the and Object.defineProperties()methods to modify the properties of the symbol type;
  4. "Well-known symbols" use global symbol constants (eg Symbol.hasInstance) to define functions for regular objects that were previously restricted to internal use. These symbols Symbol.are , allowing developers to modify the behavior of regular objects in a number of ways.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326096817&siteId=291194637