js中如何自定义迭代行为

答案:通过实现 Symbol.iterator 方法可使对象可迭代,该方法返回带有 next() 的迭代器对象,从而支持 for...of 和扩展运算符。示例中遍历 data 数组返回值和 done 状态。

在 JavaScript 中,可以通过 Symbol.iterator 来自定义对象的迭代行为。只要一个对象实现了 Symbol.iterator 方法,就可以被 for...of 循环、扩展运算符等迭代语法使用。

实现 Symbol.iterator 接口

要让一个对象可迭代,需要给它添加一个返回迭代器对象的 Symbol.iterator 方法。这个方法应返回一个带有 next() 方法的对象。

示例:
const myIterable = {
  data: ['a', 'b', 'c'],
  [Symbol.iterator]() {
    let index = 0;
    return {
      next: () => {
        if (index < this.data.length) {
          return { value: this.data[index++], done: false };
        } else {
          return { done: true };
        }
      }
    };
  }
};

// 使用 for...of 遍历 for (const item of myIterable) { console.log(item); // 输出: a, b, c }

支持多种迭代场景

一旦对象实现了 Symbol.iterator,就能用于各种需要可迭代对象的场合。

  • for...of 循环
  • 扩展运算符 [...obj]
  • 解构赋值
  • Array.from(obj)
例子:
console.log([...myIterable]); // ['a', 'b', 'c']
const [first] = myIterable;
console.log(first); // 'a'

生成器函数简化实现

使用生成器函数(function*)可以更简洁地实现自定义迭代。

const customCollection = {
  items: [1, 2, 3, 4],
  *[Symbol.iterator]() {
    for (let x of this.items) {
      yield x * 2; // 可以处理数据再输出
    }
  }
};

console.log([...customCollection]); // [2, 4, 6, 8]

基本上就这些。通过定义 Symbol.iterator,你可以控制任何对象如何被遍历,无论是简单列表还是复杂数据结构。关键是返回一个符合迭代器协议的对象,或者直接用生成器函数简化逻辑。不复杂但容易忽略细节是 done 和 value 的正确返回方式。