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,两者都是"惰性计算",适合处理大数据。
相关推荐
jktantan9 小时前
Vue keep-alive 切标签后滚动位置回顶?因为 onDeactivated 里读到的 scrollTop 是 0
前端·javascript·vue.js
总要学点什么9 小时前
第89篇:三维特效-螺旋圆效果——让螺旋臂卷起一圈圈外扩的涟漪
开发语言·javascript·ecmascript·webgl·cesium·空间分析·1024程序员节
前端精髓10 小时前
调用openrouter的免费API模型
java·前端·javascript
螺丝钉tina16 小时前
[Playwright] [02]常用命令与调试:Debug UI、Mode和 Trace Viewer
开发语言·javascript·测试工具·ui·自动化
开开心心就好17 小时前
竖式除法出题工具,整除余数混合模式
运维·服务器·前端·javascript·ocr·perl·1024程序员节
এ慕ོ冬℘゜17 小时前
JS 事件循环、宏任务微任务:单线程底层原理 + 执行顺序
开发语言·javascript·ecmascript
web打印社区17 小时前
Lodop排障总纲-常见报错一张表
开发语言·前端·javascript·chrome·websocket
程序员大阳18 小时前
副队长JavaScript教程(56)-DOM之表单操作
javascript·dom·表单操作
Dxy123931021618 小时前
JS AES加密详解
开发语言·javascript·ecmascript
FRing0319 小时前
JavaScript入门到精通三十三(异常处理、call方法、apply方法、bind方法、防抖、节流)
开发语言·前端·javascript