基本概念

Symbol:表示独一无二的值,属于类字符串数据类型,本质上可以当字符串来用。

基本用法

  • Symbol是JavaScript的第七种数据类型,前六种分别是undefined、null、Boolean、String、NUmber、Objects、Symbol。
      // 1
      let symbol = Symbol();
      typeof symbol
      // symbol 
      
      // 2 Symbol使用时不能使用new,它是一个函数,可以接收参数,仅作为描述 
      let symbol1 = Symbol('week');
      symbol1;
      // Symbol(week) 
      
      symbol1.toString();
      // "Symbol(week)"
      
      // 3
      let symbol1 = Symbol();
      let symbol2 = Symbol();
      symbol1 === symbol2;
      // false 
      
      let symbol1 = Symbol('object');
      let symbol2 = Symbol('object');
      symbol1 === symbol2;
      // false 
      
      // 4 隐式转换
      const obj = {
          toString() {
              return 'object';
          }
      };
      const symbol = Symbol(obj);
      symbol;
      // Symbol(object) 
      
      // 5 不能参与运算 
      let symbol = Symbol('symbol');
      "hello" + symbol;
      // TypeError: Cannot convert a Symbol value to a string 
      
      // 6 类型转换 
      String(symbol);
      symbol.toString();
      // Symbol(symbol) 
      
      let symbol = Symbol();
      Boolean(symbol);
      // true
      
      Number(symbol);
      // TypeError: Cannot convert a Symbol value to a number
  • description ,Symbol的描述
      const symbol = Symbol('symbollobmys');
      symbol.description;
      // "symbol"
  • symbol应用场景,对象属性名
      let symbol = Symbol();
      let a = {};
      a[symbol] = 'Hello!';
      
      let a = {
          [symbol]: 'Hello!'
      };
      
      let a = {};
      Object.defineProperty(
          a,
          symbol,
          {
              value: 'Hello!'
          }
      );
  • 属性遍历
    属性遍历中的for...in、for...of、Object.keys()、Object.getOwnPropertyNames()、JSON.stringify()都不会返回Symbol,它们会把Symbol过滤掉。但是我们可以有两种方法得到Symbol,一种是Object.getOwnPropertySymbols,另一种是Reflect.ownKeys。
      const obj = {};
      let symbol1 = Symbol('symbol1');
      let symbol2 = Symbol('symbol2');
      obj[symbol1] = 'symbol1';
      obj[symbol2] = 'symbol1';
      Object.getOwnPropertySymbols(obj);
      // [Symbol(symbol1), Symbol(symbol2)] 
      
      
      Reflect.ownKeys(obj);
      // [Symbol(symbol1), Symbol(symbol2)] 
      
      // 可以作为非私有的内部方法 
  • Symbol.for(是唯一一个能让两个Symbol相等的),寻找全局的环境下某个描述下面的这个Symbol,如果找到某一个描述下的Symbol,那么就会返回这个Symbol,如果没有找到就会生成一个新的Symbol。简而言之就是,返回当前索引Symbol。
      let symbol1 = Symbol.for('week');
      let symbol2 = Symbol.for('week');
      symbol1 === symbol2;
  • Symbol.keyFor,返回已登记的Symbol的key
      let symbol1 = Symbol.for("symbol1");
      Symbol.keyFor(symbol1);
      // symbol1 
      
      let symbol2 = Symbol("week");
      Symbol.keyFor(symbol2);
      // undefined 

内置的Symbol

  • Symbol.hasInstance,instanceof运算符调用
      class MyClass {
          [Symbol.hasInstance](obj) {
              return obj instanceof Array;
          }
      }
      
      [1, 2, 3] instanceof new MyClass();
      // true
  • Symbol.isConcatSpreadable,控制数组concat是否展开
      let array1 = [1, 2];
      [3, 4].concat(array1, 5);
      // ['a', 'b', 'c', 'd', 'e'] 
      array1[Symbol.isConcatSpreadable];
      // undefined 
      
      let array2 = [1, 2];
      array2[Symbol.isConcatSpreadable] = false;
      [3, 4].concat(array2, 5);
      // [3, 4, [1, 2], 5] 
  • Symbol.species,为衍生类指定原型
      class MyArray extends Array {
      }
      
      const one = new MyArray(1, 2, 3);
      const two = a.map(x => x);
      const three = a.filter(x => x = 1);
      
      b instanceof MyArray;
      // true 
      c instanceof MyArray;
      // true 
      
      class MyArray extends Array {
          static get [Symbol.species]() { return Array; }
      }
      
      const one = new MyArray(1, 2, 3);
      const two = a.map(x => x);
      const three = a.filter(x => x = 1);
      
      b instanceof MyArray;
      // false 
      c instanceof Array;
      // true
  • Symbol.match ,str.match调用
      class Mather {
          [Symbol.match](string) {
              return 'hello world';
          }
      }
      'e'.match(new Mather());
      // 'hello world'
  • Symbol.replace,replace调用
      const demo = {};
      demo[Symbol.replace] = () => 'hello word';
      'Hello'.replace(demo, 'World');
      // hello word
  • Symbol.search
  • Symbol.split
  • Symbol.iterator,默认遍历器
      const diyIterable = {};
      diyIterable[Symbol.iterator] = function* () {
          yield 'hello';
          yield 'word';
      };
      [...diyIterable];
      // ['hello', 'word']
  • Symbol.toPrimitive ,类型转换调用
      let object = {
          [Symbol.toPrimitive](hint) {
              switch (hint) {
              case 'number':
                  return 1;
              case 'string':
                  return 'hello';
              case 'default':
                  return 'word';
              default:
                  throw new Error('Cannot convert');
              }
          }
      };
      
      2 * object;
      // 2 
      3 + object;
      // '3word' 
      object == 'word';
      // true 
      String(object);
      // hello
  • Symbol.toStringTag , 指定[object Object]或[object Array]中object后面字符串
({
    [Symbol.toStringTag]: 'Hello'
}.toString())
// "[object Hello]" 
  • Symbol.unscopables , 指定被with排除的属性,with是一个语句,它可以扩展一个作用域链
      // with语句 扩展一个语句的作用域链 
      var a, x, y;
      var r = 10;
      with (Math) {
          a = PI * r * r;
          x = r * cos(PI);
          y = r * sin(PI / 2);
      }
      
      class MyClass {
          week() {
              return 1;
          }
          get [Symbol.unscopables]() {
              return { week: true };
          }
      }
      
      var week = function () { return 2; };
      with (MyClass.prototype) {
          week();
          // 2 
      }

知否
221 声望177 粉丝

Skrike while the iron is hot.


« 上一篇
函数的扩展
下一篇 »
Set 和 Map

引用和评论

0 条评论