Summary of basic knowledge points of Symbol type added in ES6

Keywords: Javascript Front-end

Symbol type

  Symbol is a new simple data type in ES6. The Symbol is the original value, and the instance of the Symbol is unique and immutable. The purpose of symbols is to ensure that object attributes use unique identifiers and there is no risk of attribute conflicts. Symbols are used to create unique tokens that can be used as non string object properties.

1, Basic usage of symbols

   symbols need to be initialized with the Symbol() function. Because the symbol is the original type, the typeof operator returns symbol for the symbol.

let sym = Symbol();
console.log(typeof sym); // symbol

    when calling the Symbol() function, you can pass in a string parameter to describe the symbol. This string has nothing to do with the symbol definition or identification, and can be used to debug the code. Again, symbols are unique. Symbols have no literal syntax. As long as you create a symbol () instance and use it as a new attribute of the object, you can ensure that it will not overwrite the existing object attributes, whether symbol attributes or string attributes.

let genericSymbol = Symbol();
let otherGenericSymbol = Symbol();
console.log(genericSymbol);                       // Symbol()
console.log(otherGenericSymbol);                  // Symbol()
console.log(genericSymbol == otherGenericSymbol); // false
let fooSymbol = Symbol('foo');                    
let otherFooSymbol = Symbol('foo');
console.log(fooSymbol);                            // Symbol(foo) 
console.log(otherFooSymbol);                       // Symbol(foo) 
console.log(fooSymbol == otherFooSymbol);          // false

   the Symbol() function cannot be used as a constructor, and is used with the new keyword. To avoid creating symbolic wrapper objects, like using Boolean, String or Number, they all support constructors and can be used to initialize wrapper objects containing original values:

let myBoolean = new Boolean();
console.log(typeof myBoolean); // "object"
let myString = new String();
console.log(typeof myString);  // "object"
let myNumber = new Number();
console.log(typeof myNumber);  // "object"
let mySymbol = new Symbol();   // TypeError: Symbol is not a constructor

2, Use global symbol registry

    if symbol instances need to be shared and reused in different parts of the program, you can use a string as a key to create a shared and reused symbol in the global symbol registry and use the Symbol.for() method.

  • Symbol.for()

let fooGlobalSymbol = Symbol.for('foo');	// Create global symbol
console.log(fooGlobalSymbol);         // Symbol(foo)
console.log(typeof fooGlobalSymbol);  // symbol

   Symbol.for() performs idempotent operations on each string key. ( Idempotent annotation )When a string is called for the first time, it will check the global runtime registry and find that there is no corresponding symbol, so a new symbol instance will be generated and added to the registry. Subsequent calls using the same string will also check the registry, find that there is a symbol corresponding to the string, and then return the symbol instance.

let fooGlobalSymbol = Symbol.for('foo'); 		// Create a new symbol 
let otherFooGlobalSymbol = Symbol.for('foo'); 	// Reuse existing symbols
console.log(fooGlobalSymbol === otherFooGlobalSymbol);  // true
console.log(fooGlobalSymbol);         // Symbol(foo)

   even with the same symbol description, the symbols defined in the global registry are not the same as those defined using Symbol():

let localSymbol = Symbol('foo');
let globalSymbol = Symbol.for('foo');
console.log(localSymbol === globalSymbol); // false

    symbols in the global registry must be created using the string key, so any value passed as a parameter to Symbol.for() will be converted to a string. If no parameter is passed, it is undefined. In addition, keys used in the registry are also used as symbolic descriptions.

let emptyGlobalSymbol = Symbol.for();
console.log(emptyGlobalSymbol);    // Symbol(undefined)
  • Symbol.for()

  we can use Symbol.keyFor() to query the global registry. This method receives the symbol and returns the string key corresponding to the global symbol. If the query is not a global symbol, undefined is returned. If the parameter passed in is not a symbol, an error will be reported.

let s = Symbol.for('foo');		// Create global symbol 
let s1 = Symbol.for();
console.log(Symbol.keyFor(s)); 	// foo
console.log(Symbol.keyFor(s1)); // undefined this is a string
let s2 = Symbol('bar'); 		// Create common symbols
console.log(Symbol.keyFor(s2)); // Undefined this is a value of type undefined
Symbol.keyFor(123); // TypeError: 123 is not a symbol

   note that the two undefined printed above have completely different meanings. s1 is a symbol created without parameters and with "undefined" string as descriptor. s2 is a symbol whose descriptor is "bar" not found in the global registry, and the undefined value is returned. The colors printed on the console are inconsistent.

3, Use symbols as attributes

   symbols can be used wherever strings or numeric values can be used as properties. This includes object literal properties and properties defined by Object.defineProperty() or Object.defineProperties(). Object literals can only use symbols as properties in the syntax of calculating properties. Object.defineProperty() Object.defineProperties() annotation

let s1 = Symbol('foo'),
    s2 = Symbol('bar'),
    s3 = Symbol('baz'),
    s4 = Symbol('qux');
let o = {			// Define attributes in literal form
   [s1]: 'foo val'
// You can also: o [S1] ='foo Val ';
console.log(o);	// {Symbol(foo): foo val}
Object.defineProperty(o, s2, {value: 'bar val'});
console.log(o); // {Symbol(foo): foo val, Symbol(bar): bar val}
Object.defineProperties(o, {
    [s3]: {value: 'baz val'},
    [s4]: {value: 'qux val'}
// {Symbol(foo): foo val, Symbol(bar): bar val,
//  Symbol(baz): baz val, Symbol(qux): qux val}

    secondly, we can use the Object.getOwnPropertyNames() method to return an array composed of general properties of object instances, which does not contain symbolic properties. To obtain symbolic properties, we can use the Object.getOwnPropertySymbols() method. Similarly, the returned array does not contain general properties. And Object.getOwnPropertyDescriptors() Method returns an object containing descriptors for general and symbolic properties. Reflect.ownKeys() returns two types of keys:

  note: in order to ensure the integrity of the content, the relevant methods in several objects are mentioned here, but it will not affect the learning of this knowledge point.

let s1 = Symbol('foo'),
    s2 = Symbol('bar');
let o = {
  [s1]: 'foo val',
  [s2]: 'bar val',
  baz: 'baz val',
  qux: 'qux val'
console.log(Object.getOwnPropertySymbols(o));// [Symbol(foo), Symbol(bar)]
console.log(Object.getOwnPropertyNames(o));	// ["baz", "qux"]
// {baz: {...}, qux: {...}, Symbol(foo): {...}, Symbol(bar): {...}}
// ["baz", "qux", Symbol(foo), Symbol(bar)]

    because symbol attributes are a reference to symbols in memory, symbols directly created and used as attributes will not be lost. However, if references to these attributes are not explicitly saved, you must traverse all symbol attributes of the object to find the corresponding attribute key:

let o = {
  [Symbol('foo')]: 'foo val',	// No reference to this symbol property was saved
  [Symbol('bar')]: 'bar val'
console.log(o);	// {Symbol(foo): "foo val", Symbol(bar): "bar val"}
// The downlink code uses the find method of array, the match method of string, and regular expression.
let barSymbol = Object.getOwnPropertySymbols(o)
              .find((symbol) => symbol.toString().match(/bar/));
console.log(barSymbol);	// Symbol(bar)

   ECMAScript 6 also introduces a number of common well-known symbols, which involve many advanced usages in js. This article only summarizes the basic knowledge of Symbol types. More advanced usages will be sorted out in the future.

[text notes]

Idempotent operation: an operation that returns the same result each time becomes an idempotent operation. Go back to the reading place

Object.defineProperty()/Object.defineProperties(): two ways to define object properties. For details, please refer to Type of property Go back to the reading place

Posted by louie35 on Sun, 10 Oct 2021 10:40:55 -0700