JavaScript中的迭代器和生成器

先讲迭代器(Iterator):就是"能一个个往外拿东西的容器"

你可以把迭代器想象成自动售货机:

  • 你先有一堆商品(比如数组 [1,2,3]),把它们放进售货机里,这个售货机就是迭代器;
  • 你每次按"出货"按钮(调用 next() 方法),它就给你出一个商品,出完一个就少一个;
  • 等商品出完了,再按按钮就会返回 { value: undefined, done: true }(提示"没货了");
  • 而且它只能单向前进,出了2就回不到1了,不能倒着拿。

JavaScript 迭代器的简单例子

vbscript 复制代码
// 1. 先准备一个数组(一堆商品)
const nums = [1, 2, 3];

// 2. 把数组变成迭代器(装进售货机)
const it = nums[Symbol.iterator]();

// 3. 按按钮拿东西(调用 next())
console.log(it.next()); // 输出 { value: 1, done: false }(拿第一个)
console.log(it.next()); // 输出 { value: 2, done: false }(拿第二个)
console.log(it.next()); // 输出 { value: 3, done: false }(拿第三个)
console.log(it.next()); // 输出 { value: undefined, done: true }(没货了)

迭代器的核心特点

  1. 必须有一个 next() 方法,调用后返回固定格式:{ value: 具体值, done: 是否迭代完 }
  2. 惰性获取:只有调用 next() 才会返回下一个值,不会一次性把所有值加载到内存;
  3. 用完就没:只能往前,不能回头,也不能重复用。

手动实现一个简单迭代器(理解原理)

就像自己造一个简易售货机:

javascript 复制代码
// 手动实现迭代器:模拟售货机逻辑
function createIterator(arr) {
  let index = 0; // 记录当前拿到第几个
  return {
    // 核心的 next() 方法
    next: function() {
      // 如果没拿完,返回当前值 + 未完成;否则返回 undefined + 已完成
      if (index < arr.length) {
        return { value: arr[index++], done: false };
      } else {
        return { value: undefined, done: true };
      }
    }
  };
}

// 使用这个自定义迭代器
const myIt = createIterator([10, 20, 30]);
console.log(myIt.next()); // { value: 10, done: false }
console.log(myIt.next()); // { value: 20, done: false }
console.log(myIt.next()); // { value: 30, done: false }
console.log(myIt.next()); // { value: undefined, done: true }

再讲生成器:"自动造东西的迭代器"

生成器是迭代器的升级版,你可以把它想象成现做现卖的小吃摊:

  • 迭代器是"先把所有东西准备好再往外拿"(比如先把1、2、3都放进售货机);
  • 生成器是"你要一个,我才做一个"(比如你要第一个包子,我才包第一个,要第二个才包第二个);
  • 它不用提前把所有数据存在内存里,而是"按需生成",特别省内存。

JavaScript 生成器的核心:function* + yield

function* 是生成器函数的标识(注意多了个 *),yield 就是"暂停并返回"的意思------比如你去小吃摊买包子,老板包一个给你,然后暂停,等你要下一个再继续包。

生成器的完整例子(最常用)

javascript 复制代码
// 定义生成器函数(注意 function* 和 yield)
function* makeBuns() {
  console.log("开始包第一个包子");
  yield 1; // 包好第一个,返回,暂停
  console.log("开始包第二个包子");
  yield 2; // 继续,包第二个,返回,暂停
  console.log("开始包第三个包子");
  yield 3; // 继续,包第三个,返回,暂停
}

// 调用函数,得到生成器(此时函数不会执行,只是创建生成器)
const bunGen = makeBuns();

// 第一次拿:执行到第一个yield,返回 { value: 1, done: false }
console.log(bunGen.next()); // 输出:开始包第一个包子 → { value: 1, done: false }
// 第二次拿:从暂停的地方继续,执行到第二个yield
console.log(bunGen.next()); // 输出:开始包第二个包子 → { value: 2, done: false }
// 第三次拿:继续,执行到第三个yield
console.log(bunGen.next()); // 输出:开始包第三个包子 → { value: 3, done: false }
// 第四次拿:没包子了,返回 done: true
console.log(bunGen.next()); // 输出:{ value: undefined, done: true }

生成器的实用场景:按需生成大量数据

比如要生成 100 万个数字,用数组会占满内存,但生成器只在需要时计算:

javascript 复制代码
// 生成器:按需生成数字,不占内存
function* generateBigNumbers(max) {
  let num = 1;
  while (num <= max) {
    yield num++; // 要一个,生成一个
  }
}

// 生成 100 万个数字的生成器(此时还没生成任何数字)
const bigNumGen = generateBigNumbers(1000000);

// 只拿前3个,后面的不会生成
console.log(bigNumGen.next().value); // 1
console.log(bigNumGen.next().value); // 2
console.log(bigNumGen.next().value); // 3

迭代器 vs 生成器 一句话区分(JS 版本)

  • 迭代器:已有数据的"搬运工"(把现成的东西一个个拿出来,比如数组迭代器);
  • 生成器:按需生成数据的"生产者"(没有现成数据,要的时候才造,用 function* + yield);
  • 生成器本质上是一种"自动实现了迭代器接口"的迭代器,写起来比手动迭代器简单 10 倍。

总结

  1. 迭代器:像自动售货机,提前装好物,按一次出一个,出完为止,核心是"遍历已有数据";
  2. 生成器:像现做现卖的小吃摊,不用提前备货,要一个做一个,核心是"按需生成数据",更省内存;
  3. JS 里迭代器靠 next() 方法和 { value, done } 格式,生成器靠 function* + yield,两者都是"惰性计算",适合处理大数据。
相关推荐
Crystal3282 小时前
图片懒加载
前端·javascript·代码规范
Revol_C2 小时前
开箱即用!轻量级轮询方案,支持同步获取轮询结果!
前端·javascript·设计模式
俊劫2 小时前
AI 编码技巧篇(内部分享)
前端·javascript·ai编程
多看书少吃饭4 小时前
从 ScriptProcessor 到 AudioWorklet:Electron 桌面端录音实践总结
前端·javascript·electron
钱多多8104 小时前
Vue版本降级操作指南(解决依赖冲突与版本不一致问题)
前端·javascript·vue.js·前端框架
门思科技4 小时前
门思科技正式开放 ThinkLink 纯国产化物联网平台免费部署方案
javascript·科技·物联网
San304 小时前
深度解析 React 组件化开发:从 Props 通信到样式管理的进阶指南
前端·javascript·react.js
AAA阿giao4 小时前
深度解析 React 项目架构:从文件结构到核心 API 的全面拆解
前端·javascript·react.js
刺客-Andy4 小时前
js高频面试题 50道及答案
开发语言·javascript·ecmascript