Symbols you need to know

famous symbols

A famous symbol is an unregistered symbol that is the same in different domains. If we were to list famous symbols, they would be:

  • Symbol.iterator

  • Symbol.toStringTag

  • Symbol.toPrimitive

  • Symbol.asyncIterator

  • Symbol.hasInstance

  • Symbol.isConcatSpreadable

  • Symbol.species

  • Symbol.match

  • Symbol.matchall

  • Symbol.replace

  • Symbol.search

  • Symbol.split

  • Symbol.unscopables

  • Symbol.dispose

Let's look at some examples to understand its usefulness.

Symbol.iterator

Symbol.iterator: This symbol is used to define the default iterator for objects. It is used to for-ofimplement iteration over objects in a loop, or with the spread operator.

const obj = { a: 1, b: 2, c: 3 };

obj[Symbol.iterator] = function*() {
  for (const key of Object.keys(this)) {
    yield [key, this[key]];
  }
};

for (const [key, value] of obj) {
  console.log(`${key}: ${value}`);
}

Symbol.toStringTag

Symbol.toStringTag: This symbol is used to specify Object.prototype.toStringthe string value returned when calling a method in order to provide a custom string representation for the object.

class MyClass {
  static [Symbol.toStringTag] = 'MyClass';
}

const myInstance = new MyClass();

console.log(myInstance.toString()); // outputs '[object MyClass]'

Symbol.toPrimitive

Symbol.toPrimitive: This symbol is used to specify the behavior of an object when implicitly calling valueOfmethods toString. You can use it to provide custom string and numeric representations for objects.

class Life {
  valueOf() {
    return 42;
  }

  [Symbol.toPrimitive](hint) {
    switch (hint) {
      case "number":
        return this.valueOf();
      case "string":
        return "Forty Two";
      case "default":
        return true;
    }
  }
}

const myLife = new Life();
console.log(+myLife); // 42
console.log(`${myLife}`); // "Forty Two"
console.log(myLife + 0); // 42

Symbol.asyncIterator

Symbol.asyncIterator: This symbol is used to define an asynchronous iterator for an object. You can use this to enable asynchronous iteration of objects.

class MyAsyncIterable {
  async *[Symbol.asyncIterator]() {
    for (let i = 0; i < 5; i++) {
      await new Promise(resolve => setTimeout(resolve, 1000));
      yield i;
    }
  }
}

(async () => {
  for await (const value of new MyAsyncIterable()) {
    console.log(value);
  }
})();

// Output after one second:
// 0
// Output after two seconds:
// 1
// Output after three seconds:
// 2
// Output after four seconds:
// 3
// Output after five seconds:
// 4

Symbol.hasInstance

Symbol.hasInstance: This symbol is used to confirm whether an object is an instance of the constructor. It can be used to change instanceofthe behavior of operators.

class MyArray {
  static [Symbol.hasInstance](instance) {
    return Array.isArray(instance);
  }
}

const arr = [1, 2, 3];
console.log(arr instanceof MyArray); // true

Symbol.isConcatSpreadable

Symbol.isConcatSpreadable: This symbol is used to determine whether an object should be expanded when connected to other objects. It can be used to change Array.prototype.concatthe behavior of a method.

const arr1 = [1, 2, 3];
const spreadable = { [Symbol.isConcatSpreadable]: true, 0: 4, 1: 5, 2: 6, length: 3 };

console.log([].concat(arr1, spreadable)); // [1, 2, 3, 4, 5, 6]

Symbol.species

Symbol.species: This symbol is used to specify the constructor to be used when creating a derived object. It can be used to customize the behavior of built-in methods that create new objects.

class MyArray extends Array {
  static get [Symbol.species]() {
    return Array;
  }
}

const myArray = new MyArray(1, 2, 3);
const mappedArray = myArray.map(x => x * 2);

console.log(mappedArray instanceof MyArray); // false
console.log(mappedArray instanceof Array); // true

PS: This feature may be removed in the future.

Symbol.match

Symbol.match: This symbol is used String.prototype.matchto determine the value to search for when using a method. It can be used to change the behavior of RegExpobject -like matchmethods.

const myRegex = /test/;
'/test/'.startsWith(myRegex); // Throws TypeError

const re = /foo/;
re[Symbol.match] = false;
"/foo/".startsWith(re); // true
"/bar/".endsWith(re); // false

PS: The existence of this symbol is what marks an object as a "regex".

const myRegex = /foo/g;
const str = 'How many foos in the the foo foo bar?';

for (result of myRegex[Symbol.matchAll](str)) {
  console.log(result); // we will get the matches
}

Symbol.replace

Symbol.replace: This symbol is used to String.prototype.replacedetermine the replacement value when using the method. It can be used to change the behavior of RegExpobject -like replacemethods.

const customReplace = str => str.replace(/\d+/g, match => `-${match}-`);

const customString = {
  [Symbol.replace]: customReplace
};

const originalString = "foo123bar456baz";

const result = originalString.replace(customString, '*');

console.log(result); // outputs "foo-123-bar-456-baz"

Symbol.split

Symbol.split: This symbol is used to String.prototype.splitdetermine the delimiter value when using the method. It can be used to change the behavior of RegExpobject -like splitmethods.

const { Symbol } = require('es6-symbol');

const customSplit = str => str.split(/\d+/);

const customRegExp = {
  [Symbol.split]: customSplit
};

const string = "foo123bar456baz";

string.split(customRegExp); // outputs [ 'foo', 'bar', 'baz' ]

Symbol.unscopables

Symbol.unscopables: This symbol is used to determine withwhich object properties should be excluded from the scope of the statement. It can be used to change withthe behavior of statements.

const person = {
  age: 42
};

person[Symbol.unscopables] = {
  age: true
};

with (person) {
  console.log(age);
  // Expected output: Error: age is not defined
}

Symbol.dispose

Symbol.dispose: "Explicit resource management" refers to a system in which the user explicitly manages the life cycle of a "resource" by using imperative methods (such as Symbol.dispose) or declarative methods (such as using block-scope declarations).

{ 
  console.log(1); 
  using { 
    [Symbol.dispose]() { 
      console.log(2); 
     } 
  }; 
  console.log(3); 
}
// will log 1, 3, 2

Summarize

This informative blog aims to provide an in-depth introduction to the famous symbols inherent in the JavaScript language, such as Symbol.iterator, Symbol.toStringTagand Symbol.for. These symbols represent complex and versatile tools that can be used to enhance and tune the behavior of your code. A thorough understanding of the available symbols in a JavaScript environment is key to developing high-performance, maintainable, and scalable applications. Therefore, during the conceptualization and implementation stages of the project, it is recommended to evaluate the feasibility of incorporating these symbols to make the code more concise and elegant and achieve the desired effect.

Article reprinted from: chuckQu

Original link: https://www.cnblogs.com/chuckQu/p/17271182.html

Guess you like

Origin blog.csdn.net/sdgfafg_25/article/details/131684160