跳到主要内容

Symbol

Symbol(符号)ES6新增的数据类型。符号是原始值,且符号实例是唯一、不可变的。符号的用途是确保对象属性使用唯一标识,不会发生属性冲突的危险

语法


  • 基础使用

    基础使用
    const s1Symbol = Symbol();
    const s2Symbol = Symbol();

    const obj = {
    [s1Symbol]:'s1',
    [s2Symbol]:'s2'
    }

    console.log(obj);
  • 传入描述

    • Symbol(str): 其中str为字符串类型,作为Symbol的描述,将来可以通过这个字符串来调试代码。但是这个字符串参数与Symbol定义或者Symbol标识无关。
    Symbol(str) 传入字符串参数,对Symbol进行描述
    const s1Symbol = Symbol('s1');
    const s2Symbol = Symbol('s2');

    const obj = {
    [s1Symbol]:'s1',
    [s2Symbol]:'s2'
    }

    console.log(obj);
  • 全局Symbol注册表

    如果需要运行时的不同部分需要共享和重用Symbol实例,那么可以用一个字符串作为键,在全局符号注册表中创建并重用Symbol

    • 通过Symbol.for()创建Symbol全局注册表Symbol.key()接收的是字符串

      const sSymbol = Symbol.for('s');
      const s1Symbol = Symbol.for('s');
      console.log(sSymbol === s1Symbol); // true
    • 通过Symbol.keyFor()查询Symbol全局注册表Symbol.keyFor()接收的是Symbol,返回该Symbol对应的字符串键。如果查询的Symbol不是全局的,那么返回undefined

      const sSymbol = Symbol.for('s');
      const s1Symbol = Symbol.for('s');
      console.log(sSymbol === s1Symbol); // true
      console.log(Symbol.keyFor(sSymbol)); // s
      console.log(Symbol.keyFor(s1Symbol)); // s

属性


Symbol.iterator

Symbol.iterator 一个返回一个对象默认迭代器的方法。被 for...of 使用。

Symbol.match

Symbol.match 一个用于对字符串进行匹配的方法,也用于确定一个对象是否可以作为正则表达式使用。被 String.prototype.match() 使用。

Symbol.replace

Symbol.replace 一个替换匹配字符串的子串的方法. 被 String.prototype.replace() 使用。

Symbol.search

Symbol.search 一个返回一个字符串中与正则表达式相匹配的索引的方法。被String.prototype.search() 使用。

Symbol.split

Symbol.split 一个在匹配正则表达式的索引处拆分一个字符串的方法.。被 String.prototype.split() 使用。

Symbol.hasInstance

Symbol.hasInstance 一个确定一个构造器对象识别的对象是否为它的实例的方法。被 instanceof 使用。

Symbol.isConcatSpreadable

Symbol.isConcatSpreadable 一个布尔值,表明一个对象是否应该flattened为它的数组元素。被 Array.prototype.concat() 使用。

Symbol.unscopables

Symbol.unscopables 拥有和继承属性名的一个对象的值被排除在与环境绑定的相关对象外。

Symbol.species

Symbol.species 一个用于创建派生对象的构造器函数。

Symbol.toPrimitive

Symbol.toPrimitive 一个将对象转化为基本数据类型的方法。

Symbol.toStringTag

Symbol.toStringTag 用于对象的默认描述的字符串值。被 Object.prototype.toString() 使用。

语法

场景

  • 用于精确的判断对象类型: 通过Object.prototype.toString()可以精准的判断数据类型,但是如果两个都为对象,那么可以通过Symbol.toStringTag精准的判断是哪个对象类型

    const obj1 = { name: 'obj1' };
    const obj2 = { name: 'obj2' };
    console.log(Object.prototype.toString.call(obj1)); // [object Object]
    console.log(Object.prototype.toString.call(obj2)); // [object Object]

    const obj1s = { name: 'obj1s' };
    Object.defineProperty(obj1s, Symbol.toStringTag, {
    value: 'obj1s',
    });
    const obj2s = { name: 'obj2s' };
    Object.defineProperty(obj2s, Symbol.toStringTag, {
    value: 'obj2s',
    });
    console.log(Object.prototype.toString.call(obj1s)); // [object obj1s]
    console.log(Object.prototype.toString.call(obj2s)); // [object obj2s]

Symbol.prototype.toSource

Symbol.prototype.toSource 返回该 Symbol 对象的源代码。该方法重写了 Object.prototype.toSource 方法

Symbol.prototype.toString

toString() 方法返回当前 symbol 对象的字符串表示。

注意

Symbol 对象拥有自己的 toString 方法,因而遮蔽了原型链上的 Object.prototype.toString()

语法

symbol.toString();

Symbol.prototype.valueOf

Symbol.prototype.valueOf 返回该 Symbol 对象。该方法重写了 Symbol.prototype.valueOf 方法

Symbol.prototype[@@toPrimitive]

Symbol.prototype[@@toPrimitive] 返回该 Symbol 对象。

方法


Symbol.for(key)

Symbol.for(key) 使用给定的key搜索现有的symbol,如果找到则返回该symbol。否则将使用给定的key在全局symbol注册表中创建一个新的symbol。

Symbol.keyFor(sym)

Symbol.keyFor(sym) 从全局symbol注册表中,为给定的symbol检索一个共享的?symbol key。

symbol.valueOf()

语法

const symbol = Symbol("symbol");
console.log(symbol.valueOf()); // Symbol(symbol)
console.log(symbol.valueOf() === symbol); // true

symbol.toString()

语法

const symbol = Symbol("symbol");
console.log(symbol.toString()); // Symbol(symbol)
console.log(typeof symbol.toString()); // string
console.log(symbol.toString() === symbol); // false

操作


对象包装

  • 通过**Object()**创建包装对象

    const sSymbol = Symbol('s');
    const wrappedSSymbol = Object(sSymbol);
    console.log(wrappedSSymbol); // Symbol {Symbol(s), description: 's'}
  • 通过**new Symbol()**来创建包装对象

    • 注意: Symbol() 函数不可以用作构造函数,不可以与new关键字一起使用。这样做是为了避免创建Symbol()包装对象
    const sSymbol = new Symbol('s');
    console.log(sSymbol); // Symbol is not a constructor

访问遍历

  • 通过object[symbol]访问Symbol属性

    const s1Symbol = Symbol('s1');
    const s2Symbol = Symbol('s2');

    const obj = {
    [s1Symbol]:'aaa',
    [s2Symbol]:'bbb'
    }

    console.log(obj[s1Symbol]); // aaa
    console.log(obj[s2Symbol]); // bbb
  • 通过object.symbol访问Symbol属性,结果为 undefined

    const s1Symbol = Symbol('s1');
    const s2Symbol = Symbol('s2');

    const obj = {
    [s1Symbol]:'aaa',
    [s2Symbol]:'bbb'
    }

    console.log(obj.s1Symbol); // undefined
    console.log(obj.s2Symbol); // undefined
  • 通过for……in遍历对象,不可遍历Symbol属性

    const s1Symbol = Symbol('s1');
    const s2Symbol = Symbol('s2');

    const obj = {
    [s1Symbol]:'aaa',
    [s2Symbol]:'bbb'
    }

    for(let key in obj){
    console.log(obj[key]);
    }
  • 通过Object.keys()遍历对象,不可遍历Symbol属性

    const s1Symbol = Symbol('s1');
    const s2Symbol = Symbol('s2');

    const obj = {
    [s1Symbol]:'aaa',
    [s2Symbol]:'bbb'
    }

    const result = Object.keys(obj);
    console.log(result); // []
  • 通过Object.getOwnPropertyNames(),不可获取Symbol属性

    const s1Symbol = Symbol('s1');
    const s2Symbol = Symbol('s2');

    const obj = {
    [s1Symbol]:'aaa',
    [s2Symbol]:'bbb'
    }

    const result = Object.getOwnPropertyNames(obj);
    console.log(result); // []
  • 通过Object.hasOwnProperty(),可以检测Symbol属性

    const s1Symbol = Symbol('s1');
    const s2Symbol = Symbol('s2');

    const obj = {
    [s1Symbol]:'aaa',
    [s2Symbol]:'bbb'
    }

    const result = obj.hasOwnProperty(s1Symbol);
    console.log(result); // true
  • 通过Object.getOwnPropertySymbols(),用于遍历Symbol属性

    const s1Symbol = Symbol('s1');
    const s2Symbol = Symbol('s2');

    const obj = {
    [s1Symbol]:'aaa',
    [s2Symbol]:'bbb'
    }

    const result = Object.getOwnPropertySymbols(obj);
    console.log(result); // [Symbol(s1), Symbol(s2)]