ts的迭代器和生成器

在 TypeScript(以及 JavaScript)中,迭代器和生成器是用于处理集合数据(如数组、对象等)的强大工具。它们允许你按顺序访问集合中的元素,并提供了一种控制数据访问的方式。

迭代器(Iterator) 迭代器是一个对象,它定义了一个序列,并且提供了一种方法来访问这个序列的元素。迭代器对象实现了 Iterator 接口,该接口要求它有一个 next() 方法。

Iterable 接口 一个对象如果实现了Iterable接口,那么它就是可迭代的。这个接口要求对象必须有一个Symbol.iterator方法,这个方法返回一个迭代器对象。

Iterator 接口 迭代器对象必须实现Iterator接口。这个接口定义了next()方法,该方法返回一个对象,这个对象有两个属性:value和done。value表示当前的元素值,done是一个布尔值,表示是否还有更多的元素可以迭代。

1.可迭代对象(Iterable)

一个对象如果实现了Symbol.iterator方法,它就是可迭代的。这个方法必须返回一个迭代器对象。常见的内置可迭代对象包括:Array,String,Map,Set,arguments对象(可通过Array.from()或扩展运算符使用),DOM的NodeList(部分浏览器)。

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

这些对象之所以能被for...of循环遍历,正是因为它们实现了Symbol.iterator方法。

2.迭代器(Iterator)

迭代器是一个带有next()方法的对象,调用next()返回{value,done}. value:当前值(当done:true时,value可省略或为undefined) done:布尔值,表示是否遍历完成。

ts 复制代码
const arr = [10, 20];
const iterator = arr[Symbol.iterator]();

console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());

注意:迭代器本身通常也是可迭代的(即它自己也有[Symbol.iterator()]),这样它就可以用于for...of。

3.for...of与展开运算符的工作原理
ts 复制代码
for (const item of [1, 2, 3]) {
  console.log(item);
}

背后的逻辑:

  • 获取[1,2,3] [Symbol.iterator]()
  • 不断调用.next()直到done:true

同理:

ts 复制代码
const str = "hi";
const chars = [...str];
console.log(chars)
手动实现一个可迭代对象
ts 复制代码
class Countdown {
  constructor(private start: number) {}

  [Symbol.iterator](): Iterator<number> {
    let current = this.start;
    return {
      next(): { value: number; done: boolean } {
        if (current < 0) {
          return { value: undefined, done: true };
        }
        return { value: current--, done: false };
      },
      // 可选:支持 return() 方法用于提前终止(如 break)
      return() {
        console.log("迭代被中断");
        return { value: undefined, done: true };
      }
    };
  }
}

// 使用
const countdown = new Countdown(3);
for (const n of countdown) {
  console.log(n); 
}
生成器(Generator):简化迭代器创建

生成器函数是创建迭代器的便捷方式。使用function* 定义,内部用yield暂停执行。

ts 复制代码
function* idGenerator() {
  let id = 1;
  while (true) {
    yield id++;
  }
}

const gen = idGenerator();
console.log(gen.next().value);
console.log(gen.next().value);

生成器函数返回一个生成器对象,它即是迭代器,也是可迭代对象。

你甚至可以让一个对象使用生成器作为[Symbol.iterator]

ts 复制代码
const myRange = {
  from: 1,
  to: 5,
  *[Symbol.iterator]() {
    for (let i = this.from; i <= this.to; i++) {
      yield i;
    }
  }
};

console.log([...myRange]);

迭代器协议总结:

协议:Iterable

方法:[Symbol.iterator]():Iterator

返回值:迭代器对象

说明:表示可被遍历
协议:Iterator

方法:next():{value,done}

返回值:状态对象

说明:提供下一个值
协议:可选

方法:return?():{value,done}

返回值:状态对象

说明:处理提前退出
协议:可选

方法:throw?():{value,done}

返回值:状态对象

说明:处理异常抛出

相关推荐
恋猫de小郭19 分钟前
Flutter 状态管理基准测评,一个很有趣的观点
android·前端·flutter
雪芽蓝域zzs24 分钟前
前端编辑组件wangEditor
前端
风骏时光牛马1 小时前
稳定性治理及疑难问题深度剖析与实战复盘
前端
JeffongTan9 小时前
在LWC中镶嵌VF Page获取用户IP
前端·javascript·salesforce
陆枫Larry11 小时前
Astro 是什么
前端
是立不是利13 小时前
写给设计师的 CSS 博客美学指南
前端·css
默_笙14 小时前
🏝 Docker 就是"房地产开发":从施工图纸到小区物业的容器化指南
前端·javascript
计算机魔术师14 小时前
Rohan Paul 谈用时间跨度衡量智能体能力,并引用 OpenAI 自动化研究实习生里程碑
前端
kyriewen14 小时前
我手写了个极简版 React Router——才搞懂 v6 为什么砍了这么多 API
前端·javascript·程序员