当前位置: 首页 > news >正文

深入理解 JavaScript:什么是可迭代对象 (Iterable)?

🔄 深入理解 JavaScript:什么是可迭代对象 (Iterable)?

🤔 为什么需要“可迭代”?

在 ES6 之前,我们遍历数据主要靠for循环(基于索引)或forEach。但这种方式有两个痛点:

  1. 不通用:数组能遍历,但字符串、DOM 节点列表、Map、Set 的遍历方式各不相同。
  2. 不灵活:无法自定义遍历逻辑(比如我想倒序遍历,或者只遍历偶数项)。

为了解决这个问题,ES6 引入了迭代器 (Iterator)可迭代对象 (Iterable)的概念,统一了数据访问的接口。

通俗比喻
想象你去一家自助餐厅吃饭。

  • 普通对象:像是一堆散落在桌子上的菜,没有顺序,你只能指着说“我要那个”,不能按顺序一个个拿。
  • 可迭代对象:像是传送带上的寿司。传送带有一个机制(迭代器),让你可以一个一个地按顺序获取食物,直到吃完为止。

Symbol.iterator就是那个“启动传送带的按钮”。只要一个对象身上有这个按钮,它就是“可迭代的”。


📂 目录

  1. 🛠️ 核心概念:谁是谁?
  2. 🔍 底层原理:两个协议
  3. 💻 代码实战:判断与使用
  4. ✍️ 手写实现:让普通对象可迭代
  5. ⚠️ 常见误区:Array-like vs Iterable
  6. 💡 总结

1. 🛠️ 核心概念:谁是谁?

很多初学者容易混淆这两个术语,我们先厘清定义:

✅ 可迭代对象 (Iterable)

  • 定义:实现了可迭代协议的对象。
  • 特征:对象内部必须有一个键为Symbol.iterator的方法,该方法返回一个迭代器对象
  • 常见例子Array,String,Map,Set,arguments,NodeList

✅ 迭代器 (Iterator)

  • 定义:实现了迭代器协议的对象。
  • 特征:拥有一个next()方法,每次调用返回一个包含valuedone的对象。
  • 作用:它是真正的“工人”,负责逐个吐出数据。

简单关系
可迭代对象是工厂,迭代器是工厂派出的快递员。
当你使用for...of时,JS 引擎会自动调用工厂的Symbol.iterator拿到快递员,然后一直喊next()直到送完货。


2. 🔍 底层原理:两个协议

协议一:可迭代协议 (Iterable Protocol)

只要对象拥有[@@iterator]方法(即Symbol.iterator属性),它就是可迭代的。

constarr=[1,2,3];// 检查是否有 Symbol.iterator 方法console.log(typeofarr[Symbol.iterator]);// "function"

协议二:迭代器协议 (Iterator Protocol)

Symbol.iterator方法返回的对象,必须满足以下条件:

  1. 拥有next()方法。
  2. next()返回一个对象{ value: any, done: boolean }
    • value: 当前产出的值。
    • done: 是否遍历结束(true表示结束)。

3. 💻 代码实战:判断与使用

场景一:哪些是原生的可迭代对象?

// ✅ 数组[1,2,3][Symbol.iterator];// function// ✅ 字符串"hello"[Symbol.iterator];// function// ✅ MapnewMap()[Symbol.iterator](// function// ❌ 普通对象{},)[Symbol.iterator];// undefined -> 不可迭代!

场景二:for...of的本质

当你写这段代码时:

for(constitemof[1,2,3]){console.log(item);}

JavaScript 引擎实际上在执行以下操作:

constarr=[1,2,3];constiterator=arr[Symbol.iterator]();// 1. 获取迭代器letresult=iterator.next();// 2. 第一次 next()while(!result.done){// 3. 如果没做完console.log(result.value);// 4. 处理值result=iterator.next();// 5. 继续下一个}

4. ✍️ 手写实现:让普通对象可迭代

这是面试的高频考点:如何让一个普通对象支持for...of

假设我们有一个范围对象Range,我们希望它能遍历出从startend的数字。

constrange={start:1,end:5,};// ❌ 直接遍历会报错:range is not iterable// for (let num of range) { ... }// ✅ 改造:添加 Symbol.iterator 方法range[Symbol.iterator]=function(){letcurrent=this.start;constlast=this.end;// 返回一个符合“迭代器协议”的对象return{next(){if(current<=last){return{value:current++,done:false};}else{return{value:undefined,done:true};}},};};// 现在可以愉快地遍历了!for(letnumofrange){console.log(num);// 1, 2, 3, 4, 5}// 也可以使用展开运算符console.log([...range]);// [1, 2, 3, 4, 5]

关键点
Symbol.iterator函数必须返回一个的迭代器对象。这样即使嵌套遍历或多次遍历,状态也不会冲突。


5. ⚠️ 常见误区:Array-like vs Iterable

很多“类数组对象”(Array-like)不是可迭代对象,这经常导致 Bug。

❌ 误区:argumentsNodeList

在旧版浏览器或某些环境下,document.querySelectorAll返回的NodeList可能没有Symbol.iterator(虽然现代浏览器大多已支持,但需警惕兼容性)。

constdivs=document.querySelectorAll("div");// ❌ 在某些旧环境或特定对象上可能失效// for (let div of divs) { ... }// ✅ 安全做法:使用 Array.from 转换constdivArray=Array.from(divs);divArray.forEach((div)=>console.log(div));

✅ 最佳实践:如何安全地遍历?

如果你不确定一个对象是否可迭代,可以使用以下工具函数检测:

functionisIterable(obj){// 检查 null/undefinedif(obj==null)returnfalse;// 检查是否有 Symbol.iterator 方法且类型为函数returntypeofobj[Symbol.iterator]==="function";}console.log(isIterable([]));// trueconsole.log(isIterable({}));// falseconsole.log(isIterable(""));// true

6. 💡 总结

概念说明关键方法/属性
可迭代对象能被for...of遍历的对象obj[Symbol.iterator]
迭代器负责逐个返回数据的对象iterator.next()
next() 返回值包含值和状态的对象{ value: ..., done: ... }
原生可迭代Array, String, Map, Set, arguments 等-
非可迭代普通 Object{}-

🚀 博主寄语
可迭代协议是 JavaScript 统一数据访问方式的伟大尝试。
它不仅让for...of成为可能,还支撑起了生成器 (Generator)、异步迭代器 (Async Iterator) 等高级特性。

记住口诀
想要遍历用for...of
对象必须有iterator
next方法吐数据,
done为真停脚步。

希望这篇文档能帮你彻底搞懂可迭代对象!如果有疑问,欢迎在评论区留言。👇

喜欢这篇文章吗?记得点赞、收藏、转发哦!❤️

http://www.jsqmd.com/news/791754/

相关文章:

  • 在RK3399上跑通ORB-SLAM2和VINS-MONO,我踩过的那些坑(含RealSense D435i兼容性测试)
  • 告别手动开关!用ESP8266+Arduino IDE实现高精度定时控制(实测误差<1秒)
  • TikTok评论采集全攻略:零代码批量获取用户反馈的终极方案
  • 如何3分钟掌握终极树状书签管理神器:Neat Bookmarks完全指南
  • Windows Defender完全掌控指南:3分钟彻底禁用Windows Defender的终极解决方案
  • 抖音批量下载工具架构解析:从技术实现到实战配置指南
  • KMS智能激活工具终极指南:一键解决Windows和Office激活难题
  • 别再傻傻分不清!同步复位、异步复位、Byte Enable,一个HDLbits实验搞定所有D触发器变种
  • 从光衰减到泥沙传输:深入拆解FVCOM-FABM-ERSEM耦合中的关键物理过程
  • 企业内如何利用Taotoken实现API Key的精细化权限管理与审计
  • 老旧S7-200/300如何低成本联网?实测第三方通讯桥接器在IFIX项目中的应用
  • 大模型治理不是加监控,而是重定义SLI:奇点智能大会联合信通院发布的《大模型服务治理黄金标准V1.2》正式版,仅开放下载72小时(附11个生产环境故障复盘案例)
  • 镜像视界(浙江)科技有限公司 —— 数字孪生与视频孪生领域的深度引领者
  • 如何用AI算法征服2048游戏?完整教程带你从新手到高手
  • 当你的客户想运行自己的工作流,你该怎么办
  • 从JPG到GeoTIFF:一次搞懂JGW文件、仿射变换与栅格数据的地理配准核心原理
  • 从‘//’到‘///’:解锁C#注释的正确姿势与隐藏的IDE效率技巧
  • FreeRouting终极指南:如何快速掌握开源PCB自动布线工具
  • STM32F103RCT6驱动ADS1115:从IIC时序到电压换算的保姆级避坑指南
  • 从HarryNull密码游戏入门CTF:手把手带你破解前10关(附完整思路与工具)
  • FFmpeg GUI终极指南:图形化音视频处理神器快速上手
  • 怎么去图片上原有的水印?图片去水印工具推荐,图片去水印方法汇总,2026最新在用的去水印方案全解析, - 爱上科技热点
  • 如何用免费AI工具实现专业级语音转文字:Faster-Whisper-GUI完全指南
  • Android Studio中文语言包:三步告别英文困扰的终极指南
  • 告别传统MLP!用TensorFlow 2.2复现Deep Biaffine Attention依存解析模型(附Colab代码)
  • 部署与可视化系统:2026 年大厂标配:Triton Inference Server 结合模型分析器优化 YOLO 多模型并发
  • 2026年3月,西双版纳超赞民宿推荐来袭,西双版纳住宿/民宿/住宿/西双版纳酒店/西双版纳民宿/酒店,西双版纳民宿推荐 - 品牌推荐师
  • 暗黑3按键助手完全指南:5分钟掌握自动化技能操作
  • 【光学】基于matlab全变异正则化泊松模型用于X射线透视成像的相位反演【含Matlab源码 15426期】
  • IDM试用重置终极指南:轻松实现无限试用,告别30天限制