用途是确保对象属性使用唯一标识符,不会发生属性冲突的危险

基本用法

  1. // 需要使用Symbol函数初始化,不可以使用new操作符,为了防止出现包装对象的情况
  2. let sym = Symbol();
  3. console.log(typeof sym); // symbol
  4. // 如需使用对象形式的可以自行包装
  5. let mySymbol = Symbol();
  6. let myWrappedSymbol = Object(mySymbol);
  7. console.log(typeof myWrappedSymbol); // "object"
  8. // 可以传入参数,做作为符号描述,但是和标识本身并无关系
  9. let fooSymbol = Symbol('foo');
  10. let otherFooSymbol = Symbol('foo');
  11. console.log(fooSymbol == otherFooSymbol); // false
  • 你只要创建 Symbol()实例并将其 用作对象的新属性,就可以保证它不会覆盖已有的对象属性,无论是符号属性还是字符串属性。

    全局注册表

  • 用Symbol.for(‘foo’),可以重用全局内已有符号,不传参数,会返回 Symbol(undefined)。

    1. let fooGlobalSymbol = Symbol.for('foo'); // 创建新符号
    2. let otherFooGlobalSymbol = Symbol.for('foo'); // 重用已有符号
    3. console.log(fooGlobalSymbol === otherFooGlobalSymbol); // true
  • 用 Symbol.keyFor() 搜索全局注册表,如果不是注册过得Symbol返回undefined ```javascript // 创建全局符号 let s = Symbol.for(‘foo’); console.log(Symbol.keyFor(s)); // foo // 创建普通符号 let s2 = Symbol(‘bar’); console.log(Symbol.keyFor(s2)); // undefined

/ 如果全局搜索不到,会报错 / Symbol.keyFor(123); // TypeError: 123 is not a symbol

  1. <a name="cpDS6"></a>
  2. ### 作为对象的属性使用
  3. - 设置set操作
  4. ```javascript
  5. let s1 = Symbol('foo'),
  6. s2 = Symbol('bar'),
  7. s3 = Symbol('baz'),
  8. s4 = Symbol('qux');
  9. // 直接设置
  10. let o = {
  11. [s1]: 'foo val'
  12. };
  13. // 属性设置
  14. Object.defineProperty(o, s2, {value: 'bar val'});
  15. // 多属性设置
  16. Object.defineProperties(o, {
  17. [s3]: {value: 'baz val'},
  18. [s4]: {value: 'qux val'}
  19. });
  • 取出get操作 ```javascript let s1 = Symbol(‘foo’),
    1. s2 = Symbol('bar');
    let o = { [s1]: ‘foo val’, [s2]: ‘bar val’, baz: ‘baz val’, qux: ‘qux val’ }; // getOwnPropertySymbols 和 getOwnPropertyNames 二者取出来的内容互斥 // 1. getOwnPropertySymbols取出symbol的属性和key // 2. getOwnPropertyNames 取出不是常规的属性和key — 非symbol定义的

console.log(Object.getOwnPropertySymbols(o)); // [Symbol(foo), Symbol(bar)] console.log(Object.getOwnPropertyNames(o)); // [“baz”, “qux”]

// 3. getOwnPropertyDescriptors可以取出所有的属性和key console.log(Object.getOwnPropertyDescriptors(o)); // {baz: {…}, qux: {…}, Symbol(foo): {…}, Symbol(bar): {…}}

// 4. Reflect.ownKeys(), 取出所有的key console.log(Reflect.ownKeys(o)); // [“baz”, “qux”, Symbol(foo), Symbol(bar)]

  1. - **注意: ** 如果 没有显式地保存对这些属性的引用,那么必须遍历对象的所有符号属性才能找到相应的属性键
  2. ```javascript
  3. let o = {
  4. [Symbol('foo')]: 'foo val',
  5. [Symbol('bar')]: 'bar val'
  6. };
  7. console.log(o);
  8. // {Symbol(foo): "foo val", Symbol(bar): "bar val"}
  9. let barSymbol = Object.getOwnPropertySymbols(o)
  10. .find((symbol) => symbol.toString().match(/bar/));
  11. console.log(barSymbol);
  12. // Symbol(bar)

常用内置符号

  1. Symbol.asyncIterator —- 异步迭代和 for-await-of 循环
  2. Symbol.hasInstance —- instanceof 操作符使用
  3. Symbol.isConcatSpreadable —- 是否可以使用 Array.prototype.concat() 方法,如果为false,不会打平数组
  4. Symbol.iterator —- for-of 语句使用
  5. Symbol.match —- String.prototype.match()方法使用,可以改变正则的默认返回形式
  6. Symbol.replace —- String.prototype.replace()方法使用 , 可以重写replace的实现
  7. Symbol.search —- String.prototype.search()方法使用, 获取正则开始索引
  8. Symbol.species —- 用于替换当前的instanceof的实例对象
  9. Symbol.split —- String.prototype.split()方法使用
  10. Symbol.toPrimitive —- 该方法将对象转换为相应的原始值,可以控制返回的原始行为。对象默认行为返回[object Object] 可以使用这个符号,转换为输出其他内容 p54
  11. Symbol.toStringTag —- Object.prototype.toString()使用,对象默认行为返回[object Object] 可以使用这个符号,转换为输出 [object 其他内容]
  12. Symbol.unscopables —- 可以排除在with使用环境外(不推荐使用)