惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

N
News and Events Feed by Topic
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Hugging Face - Blog
Hugging Face - Blog
S
SegmentFault 最新的问题
IT之家
IT之家
M
MIT News - Artificial intelligence
博客园_首页
aimingoo的专栏
aimingoo的专栏
C
Check Point Blog
B
Blog
人人都是产品经理
人人都是产品经理
爱范儿
爱范儿
宝玉的分享
宝玉的分享
Martin Fowler
Martin Fowler
L
LangChain Blog
Last Week in AI
Last Week in AI
Engineering at Meta
Engineering at Meta
Microsoft Security Blog
Microsoft Security Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
F
Fortinet All Blogs
罗磊的独立博客
博客园 - 叶小钗
H
Help Net Security
Google Online Security Blog
Google Online Security Blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
The Last Watchdog
The Last Watchdog
S
Security @ Cisco Blogs
Google DeepMind News
Google DeepMind News
Cyberwarzone
Cyberwarzone
月光博客
月光博客
C
Cybersecurity and Infrastructure Security Agency CISA
博客园 - 司徒正美
S
Schneier on Security
V
Vulnerabilities – Threatpost
T
Troy Hunt's Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
博客园 - 【当耐特】
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Forbes - Security
Forbes - Security
D
Darknet – Hacking Tools, Hacker News & Cyber Security
雷峰网
雷峰网
Hacker News - Newest:
Hacker News - Newest: "LLM"
S
Secure Thoughts
V
Visual Studio Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
云风的 BLOG
云风的 BLOG
T
Tailwind CSS Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
Hacker News: Ask HN
Hacker News: Ask HN
The GitHub Blog
The GitHub Blog

博客园 - 刘俊涛的博客

qoder-体验分享 50+专家角色+多代理框架,一个人就能建起一支AI 公司 小米突然放大招!2亿 Token 免费领,最后几天冲刺! 这个项目把浏览器“干了30年的事”干掉了:Pretext 为什么突然爆火? 通用商品打标模块实现方案(基于位运算,适配多框架多语言) 后端工程中使用 Model + Trait 设计可复用的数据模型(完整实现示例) 最小阻力之路 U盘打不开 : 文件损坏 : 提示需要格式化?用CHKDSK轻松修复教程 祂看顧麻雀(His Eye Is on the Sparrow)鄭漢良 Spark性能调优实战笔记 Spark神操作:轻松拿捏公司“历史烂数据”,一人干翻十年脏表 特定血型血液生成的研究进展:化学合成与微生物生产技术路线 禁止直接 update 业务关键字段 非暴力沟通 PHP 8.1+ 引入的 枚举(Enum) 类型 PHP 8.5 新特性速览:管道操作符、clone with、闭包增强与更多实用功能 从错误中学习 产品拆解到底怎么做?8步框架,新手产品经理必学干货! 《创作与爱:托芙·扬松传》读书笔记 MongoDB 端口安全加固方案 为什么软件反应特别慢?一次因版本架构错误导致的性能问题排查记录 【Go 语言神器】iota 到底是什么?为什么高手都爱用它?
别再把一切都变成数组了:用迭代器让 JavaScript 既快又省心
刘俊涛的博客 · 2026-02-09 · via 博客园 - 刘俊涛的博客

别再把一切都变成数组了:用迭代器让 JavaScript 既快又省心

为什么你每天写的 .filter().map().slice() 可能在“偷懒”反而浪费更多

在前端与 Node 应用里,我们经常会这样链式处理数组:

const visibleItems = items
  .filter(isVisible)
  .map(transform)
  .slice(0, 10);

这种写法看上去清晰优雅,但背后其实做了三次 完整数组遍历三个中间数组分配

  1. filter() 会创建新数组
  2. map() 又创建新数组
  3. slice() 仍然创建新数组

即便我们最后只需要 10 条结果,它依然处理了全部数据。这个效率低下的问题是显性的、也是巨大的。


做更少的工作:JavaScript 原生 迭代器助手的崛起

从 ECMAScript 2025/2026 起,JavaScript 提供了全新的 迭代器助手(Iterator Helpers) API,它们可以搭建 懒执行(lazy)数据管道

名称 作用
filter(fn) 懒筛选
map(fn) 懒映射
take(n) 只取前 n 条
drop(n) 跳过前 n 条
toArray() 最终收集为数组
(其他如 flatMap, some, every) 更多实用功能

迭代器助手的关键特点是只有消费时才执行,并且不会生成中间数组。


懒执行示例对比:数组 vs 迭代器

传统数组方式(内存消耗高)

function getTopVisible(items) {
  return items
    .filter(x => x.visible)  // 数组分配
    .map(x => transform(x))  // 再次数组分配
    .slice(0, 50);           // 再次数组分配
}

上述函数需要在内存中创建多个中间数组,若 items 是几万条甚至更多数据,内存峰值将很高。

迭代器优化方式(按需处理)

function getTopVisibleIterator(items) {
  return items
    .values()                // 得到迭代器
    .filter(x => x.visible)  // 懒过滤
    .map(x => transform(x))  // 懒映射
    .take(50)                // 只取 50 条
    .toArray();              // 仅把结果转成数组
}

这里:

  • .values() 生成迭代器而不是数组

  • .filter(), .map() 都是懒操作,不创建数组

  • .take(50) 遇到满足条件的 50 条就会停止

  • 最终 toArray() 只会产生最终需要的 50 条数据 分配在内存里

    (注意 toArray() 类似 Array.from(iterator),它才会产生数组)

这种按需处理对于大数据集或 UI 驱动的渲染场景尤其有用。


实战场景:滚动列表、分页 API 以及流式数据

示例:无限滚动列表

function* rows(data) {
  for (const row of data) {
    yield row;
  }
}

const visible = rows(bigDataset)
  .filter(isInViewport)
  .take(30)
  .toArray();

// 只处理屏幕可见部分
render(visible);

优点:

  • 不会预处理所有数据
  • 不会创建上千条中间数组
  • 代码语义清晰

示例:分页 API(AsyncIterator)

async function* fetchPages() {
  let page = 1;
  while (true) {
    const res = await fetch(`/api/list?page=${page++}`);
    if (!res.ok) return;
    yield* await res.json();
  }
}

const top20 = await fetchPages()
  .filter(isValid)
  .take(20)
  .toArray();

render(top20);

这个模式:

  • 只按需拉取 API 数据
  • 不需要手写计数器
  • 不需要缓存所有页数据

这种写法比先 fetch 所有页再筛选高效得多。


何时不适合迭代器?

懒管道优点明显,但它不是万能的。以下几种情况数组更合适:

  • 需要随机访问(如 items[5])
  • 需要多次多遍历同一数据
  • 数据集本身非常小,开发简易性更重要

迭代器是一次性的(consumed once),所以在这些场景强行使用反而不方便。


性能与内存对比

对比传统数组操作和迭代器:

// 数组版本
function loopArray(data) {
  return data
    .map(x => x * 2)
    .filter(x => x % 3 === 0)
    .slice(0, 100);
}

// 迭代器版本
function loopIterator(data) {
  return data
    .values()
    .map(x => x * 2)      // 不会创建数组
    .filter(x => x % 3 === 0)
    .take(100)
    .toArray();           // 仅最终 100 条
}

结果:

  • 数组版本会产生 3 次数组分配及遍历
  • 迭代器版本只会在结果阶段分配一次最多 100 条数据
  • 内存峰值明显更低

这对于大数据集处理尤其明显,在 Node 后端批量计算、前端大表格渲染等场景能显著降低内存压力。


做更少的工作,写更优雅的代码

JavaScript 的传统数组链式方法易写,却隐藏了大量不必要的工作。迭代器助手 API 引入了 懒执行、按需处理与提前停止 的能力,让我们可以:

  • 避免中间数组带来的内存浪费
  • 让处理逻辑更贴合业务需求
  • 写出可维护、性能更强的数据管道

一句话总结:

如果你不需要整个数组,就不要一次性把它都生成出来。

JavaScript, #性能优化, #实践指南, #懒执行

参考资料与引用

以下引用均来自官方原文与业内权威资料,供读者深入阅读和验证。

  1. 原始技术灵感来源
    Stop turning everything into arrays (and do less work instead) — Matt Smith,讨论了数组链式方法的隐性成本以及 JavaScript 迭代器助手的优势与使用模式。可阅读原文获取详细说明与示例。 原文博客:Stop turning everything into arrays (and do less work instead)
  2. 迭代器在实践中的优势
    迭代器的惰性(lazy)特性使其在不必访问整个集合时能够避免不必要的内存分配,与传统数组方法做对比。 oai_citation:2‡优网科技
  3. 社区反馈与使用讨论
    该技术在开发者社区(如 Reddit、Echo JS)中也引发了讨论,尤其是对 lazy execution、take() 提前终止、toArray() 终止链式管道等特性的关注。 oai_citation:3‡回声JS

欢迎关注公-众-号【TaonyDaily】、留言、评论,一起学习。

公众号

Don’t reinvent the wheel, library code is there to help.

文章来源:刘俊涛的博客


看完有收获的话,别忘了点个赞、留个言,或者转发给身边的朋友吧!你的支持让我更有动力分享更多好内容~☺️