• 你需要知道的Symbols


    著名symbol

    著名symbol是一个在不同领域中都相同且未注册的symbol。如果我们要列出著名symbol,它们会是:

    • 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

    让我们看一些例子来了解其有用性。

    Symbol.iterator

    Symbol.iterator:该symbol被用来为对象定义默认的迭代器。它被用来在for-of循环中实现对对象的迭代,或用于扩展操作符。

    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:该symbol被用来指定在调用Object.prototype.toString方法时返回的字符串值,以便为对象提供自定义的字符串表示形式。

    class MyClass {
      static [Symbol.toStringTag] = 'MyClass';
    }
    
    const myInstance = new MyClass();
    
    console.log(myInstance.toString()); // outputs '[object MyClass]'
    

    Symbol.toPrimitive

    Symbol.toPrimitive:该symbol被用来指定对象在隐式调用valueOftoString方法时的行为。可以用它来为对象提供自定义的字符串和数字表示形式。

    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:该symbol被用来为对象定义一个异步的迭代器。可以用它来为对象启用异步迭代。

    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:该symbol被用来确认一个对象是否是构造函数的实例。它可以用来更改instanceof操作符的行为。

    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:该symbol被用来确定对象在与其他对象连接时是否应该被展开。它可以用来更改Array.prototype.concat方法的行为。

    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:该symbol被用来指定创建派生对象时要使用的构造函数。它可以用来自定义创建新对象的内置方法的行为。

    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
    

    P.S:这一功能在未来可能会被删除。

    Symbol.match

    Symbol.match:该symbol被用来在使用String.prototype.match方法时确定要搜索的值。它可以用来更改类似于RegExp对象的match方法的行为。

    const myRegex = /test/;
    '/test/'.startsWith(myRegex); // Throws TypeError
    
    const re = /foo/;
    re[Symbol.match] = false;
    "/foo/".startsWith(re); // true
    "/bar/".endsWith(re); // false
    

    P.S: 这个symbol的存在是标志着一个对象是"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:该symbol被用来在使用String.prototype.replace方法时确定替换值。它可以用来更改类似于RegExp对象的replace方法的行为。

    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:该symbol被用来在使用String.prototype.split方法时确定分隔值。它可以用来更改类似于RegExp对象的split方法的行为。

    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:该symbol被用于确定应该从with语句的作用域中排除哪些对象属性。它可以用来更改with语句的行为。

    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:“显式资源管理”是指用户通过使用命令式方法(如Symbol.dispose)或声明式方法(如使用块作用域声明)显式地管理“资源”的生命周期的系统。

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

    总结

    这篇信息性的博客旨在深入介绍JavaScript语言中固有的著名symbol,例如Symbol.iteratorSymbol.toStringTagSymbol.for。这些symbol代表着复杂而多才多艺的工具,可以用来增强和调节代码的行为。在JavaScript环境中全面理解可用symbol是开发高性能、可维护和可扩展应用程序的关键。因此,在项目的概念化和实施阶段,建议评估将这些symbol纳入其中的可行性,以使代码更加简洁、优雅,达到预期的效果。

    以上就是本文的全部内容,如果对你有所帮助,欢迎收藏、点赞、转发~

  • 相关阅读:
    后端研发工程师面经——数据库
    设计模式:外观模式(C++实现)
    Babylonjs学习笔记(三)——创建天空盒
    学SLAM的女生,很酷
    ByConity常用SQL语句
    Linux下的截图工具 —— Spectable
    新版TCGA的甲基化数据分析
    CF1781F Bracket Insertion(2700*) 题解(括号匹配DP)
    centos+docker+pytest+jenkins+gitee+allure部署自动化环境
    树套树P3380
  • 原文地址:https://www.cnblogs.com/chuckQu/p/17271182.html