1. 符号是 ES6 新增的一个数据类型,它通过使用函数 Symbol (符号描述) 来创建符;
  2. 符号设计的初衷,是为了给对象设置私有属性;
  3. 共享符号可以根据某个符号名称 (符号描述) 能够得到同一个符号,通过使用函数 Symbol.for(“符号名/符号描述”) 来创建;

Symbol 特点

  1. 没有字面量 (每个 Symbol 都是通过 Symbol 函数创建)

  2. 每次调用 Symbol 函数得到的符号永远不相等,无论符号名是否相同;

  3. 符号可以作为对象的属性名存在,这种属性称之为符号属性 (es6 之前对象属性只能是字符串或者数字)

  4. 符号无法被隐式转换,不能被用于数学运算、字符串拼接或其他隐式转换,但符号可以通过 String 构造函数显式的转换为字符串;

  5. 不能被 new 执行,但是有原型;

Symbol.iterator

  1. 该符号可以判断数据是否拥有迭代功能,它可以影响数据迭代器遍历功能;

  2. 只有对象具备 Symbol.iterator 才是可以被遍历的数据结构;

迭代器协议

  1. 迭代器协议定义了产生一系列值的一个标准方式,迭起协议规定需要返回一个带 next() 方法的对象,next() 可以被多次执行,每次执行都会返回一个对象,该对象包含 donevalue 两个属性:

    1. done:是一个 boolean,在没有迭代完时返回 false,迭代完成后返回 true
    2. value:就是被迭代的返回值,当 donetrue 时可以省略;
  2. 实现了以上两点才会满足一个迭代器协议;

手动实现一个迭代器

const obj = {
  store: ['foo', 'bar', 'baz'],
  [Symbol.iterator]: function () {
    let index = 0

    return {
      next: () => {
        const result = {
          value: this.store[index],
          done: index++ >= this.store.length
        }

        return result
      }
    }
  }
}

// 实现了 iterator 迭代器协议,则可以使用 for...of 遍历
for (const item of obj) {
  console.log('循环体', item)
}
// 循环体 foo
// 循环体 bar
// 循环体 baz

Symbol.toStringTag

该知名符号会影响 Object.prototype.toString 的返回值;

JavaScript
JavaScript
class Person {}

const p = new Person();
console.log(Object.prototype.toString.apply(p));  // [object Object]
// Symbol.toStringTag 可以实现使用 toString 判断类型时更加精确的知道自身的构造函数
class Person {
  constructor() {
    // 通过 Symbol.toStringTag 改写  Object.prototype.toString.call 更准确
    this[Symbol.toStringTag] = "Person"
  }
}

const p = new Person();
console.log(Object.prototype.toString.apply(p));  // [object Person]

Symbol 应用

设置私有属性

// 实现类中私有属性使其外面不能访问到只能内部使用
const Hero = (() => {
  const getRandom = Symbol();

  return class {
    constructor(a) {
      this.a = a;
    }

    attack() {
      const dmg = this.a * this[getRandom](0.8, 1.1);
      console.log(dmg);
    }

    // 私有属性随机函数
    [getRandom](min, max) {
      return Math.random() * (max - min) + min;
    }
  }
})();

// 测试
const h = new Hero(3);
h.attack();  // 不报错
h[Symbol]()  // 报错

// 也可以使用一些不寻常的手段获取使用(强烈不建议)
const sybs = Object.getOwnPropertySymbols(Hero.prototype);
console.log(h[sybs[0]](3));  // 不报错

唯一属性值

打赏作者
您的打赏是我前进的动力
微信
支付宝
评论

中午好👏🏻,我是 ✍🏻   疯狂 codding 中...

粽子

这有关于前端开发的技术文档和你分享。

相信你可以在这里找到对你有用的知识和教程。

了解更多

目录

  1. 1. Symbol 特点
  2. 2. Symbol.iterator
    1. 2.1. 迭代器协议
    2. 2.2. 手动实现一个迭代器
  3. 3. Symbol.toStringTag
  4. 4. Symbol 应用
    1. 4.1. 设置私有属性
    2. 4.2. 唯一属性值