ES6从入门到精通:Symbol与迭代器

Symbol 的基本概念

Symbol 是 ES6 引入的一种新的原始数据类型,表示独一无二的值。Symbol 值通过 Symbol() 函数生成,即使传入相同的描述符,生成的 Symbol 值也不相等。

javascript 复制代码
const s1 = Symbol('foo');
const s2 = Symbol('foo');
console.log(s1 === s2); // false

Symbol 的描述符主要用于调试,可以通过 description 属性获取。

javascript 复制代码
console.log(s1.description); // 'foo'

Symbol 的使用场景

Symbol 主要用于对象属性的键,避免属性名冲突。由于 Symbol 值唯一,适合作为对象的私有属性或特殊标识。

javascript 复制代码
const obj = {
  [Symbol('key')]: 'value'
};
console.log(obj[Symbol('key')]); // undefined,因为 Symbol 值不同

Symbol 还可以用于定义类的私有成员。

javascript 复制代码
const _private = Symbol('private');
class MyClass {
  constructor() {
    this[_private] = 'secret';
  }
  getSecret() {
    return this[_private];
  }
}

内置 Symbol 值

ES6 提供了许多内置的 Symbol 值,用于实现语言内部行为。例如:

  • Symbol.iterator: 定义对象的默认迭代器。
  • Symbol.toStringTag: 定制对象的 toString() 行为。
  • Symbol.hasInstance: 定制 instanceof 操作符的行为。
javascript 复制代码
class MyArray {
  static [Symbol.hasInstance](instance) {
    return Array.isArray(instance);
  }
}
console.log([] instanceof MyArray); // true

迭代器与可迭代协议

迭代器是一种设计模式,允许按照顺序访问集合对象的元素。ES6 引入了可迭代协议和迭代器协议。

  • 可迭代协议 : 对象必须实现 @@iterator 方法(即 Symbol.iterator 属性),返回一个迭代器。
  • 迭代器协议 : 迭代器必须实现 next() 方法,返回 { value, done } 对象。
javascript 复制代码
const iterable = {
  [Symbol.iterator]() {
    let step = 0;
    return {
      next() {
        step++;
        if (step <= 3) {
          return { value: step, done: false };
        }
        return { value: undefined, done: true };
      }
    };
  }
};
for (const value of iterable) {
  console.log(value); // 1, 2, 3
}

生成器与迭代器

生成器函数(function*)返回一个生成器对象,该对象既是迭代器,也是可迭代对象。生成器简化了迭代器的实现。

javascript 复制代码
function* simpleGenerator() {
  yield 1;
  yield 2;
  yield 3;
}
const gen = simpleGenerator();
console.log(gen.next().value); // 1
console.log([...gen]); // [2, 3]

内置可迭代对象

许多 ES6 内置对象是可迭代的,例如数组、Set、Map、字符串等。它们都实现了 Symbol.iterator 方法。

javascript 复制代码
const arr = [1, 2, 3];
const iterator = arr[Symbol.iterator]();
console.log(iterator.next().value); // 1

自定义可迭代对象

通过实现 Symbol.iterator 方法,可以自定义对象的迭代行为。

javascript 复制代码
class Range {
  constructor(start, end) {
    this.start = start;
    this.end = end;
  }
  *[Symbol.iterator]() {
    for (let i = this.start; i <= this.end; i++) {
      yield i;
    }
  }
}
const range = new Range(1, 5);
console.log([...range]); // [1, 2, 3, 4, 5]

Symbol 与迭代器的结合

Symbol 和迭代器可以结合使用,实现更灵活的对象行为。例如,通过 Symbol.iterator 定义对象的默认迭代方式。

javascript 复制代码
const obj = {
  data: [1, 2, 3],
  [Symbol.iterator]() {
    let index = 0;
    return {
      next: () => {
        if (index < this.data.length) {
          return { value: this.data[index++], done: false };
        }
        return { value: undefined, done: true };
      }
    };
  }
};
console.log([...obj]); // [1, 2, 3]

总结

Symbol 是 ES6 引入的独一无二的值,可用于对象属性的键或特殊标识。迭代器协议和可迭代协议提供了统一的遍历机制。生成器简化了迭代器的实现。通过 Symbol.iterator 可以自定义对象的迭代行为。这些特性为 JavaScript 提供了更强大的元编程能力。

相关推荐
天平32 分钟前
油猴脚本创建webworker踩坑记录
前端·javascript·typescript
原则猫2 小时前
前端基础大厦
前端
陈随易3 小时前
编程语言级别的Skill市场,AI Agent 的未来形态
前端·后端·程序员
SoaringHeart4 小时前
Flutter进阶:基于 EasyRefresh 的下拉刷新封装 n_easy_refresh_mixin.dart
前端·flutter
IT_陈寒6 小时前
Vite的热更新突然不香了,排查三小时差点砸键盘
前端·人工智能·后端
子兮曰6 小时前
Agency-Agents 深度解析:400+ AI 专家的"梦之队"如何重塑开发工作流
前端·后端·vibecoding
山河木马7 小时前
渲染管线-计算得到gl_Position(顶点着色器)之后续GPU流程
javascript·webgl·图形学
竹林8187 小时前
用 The Graph 查询链上数据实战:从手搓 RPC 到 Subgraph,我的 NFT 项目数据加载快了 10 倍
前端·javascript
妙码生花7 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(十九):点选验证码代码逐行目检
前端·后端·go
Awu12278 小时前
⚡从零开发 Agent CLI(五)实现一个可治理、可扩展的工具系统
前端·人工智能·claude