JavaScript中用for-of遍历Map和Set安全且推荐,因二者原生实现Symbol.iterator接口;Map默认按插入顺序返回[key, value]数组,可解构遍历或调用keys()/values();Set直接返回元素值,values()与keys()行为一致;遍历时不可修改结构,否则行为未定义,应先收集后统一处理;现代环境原生支持,旧环境需Babel转译及core-js补丁。

JavaScript中用for-of循环遍历Map和Set是安全且推荐的方式,因为它们原生实现了Symbol.iterator接口,无需手动调用next()或处理done状态。
Map的for-of遍历:默认返回键值对
Map的迭代器默认按插入顺序产出[key, value]数组。直接用for-of即可解构使用:
- 遍历整个键值对:
for (const [key, value] of myMap) { ... } - 只取键:
for (const key of myMap.keys()) { ... } - 只取值:
for (const value of myMap.values()) { ... }
注意:myMap[Symbol.iterator] === myMap.entries,所以for-of等价于myMap.entries()。遍历时不会触发额外拷贝,底层复用内部链表结构,性能可靠。
Set的for-of遍历:直接获取元素值
Set的迭代器默认按插入顺序产出每个唯一元素本身:
立即学习“Java免费学习笔记(深入)”;
- 标准遍历:
for (const item of mySet) { ... } - 也可显式调用:
for (const item of mySet.values()) { ... }(values()与keys()在Set中行为一致)
不支持mySet.entries()返回键值对(因无键概念),但entries()仍存在,返回[value, value]形式——一般无需使用。
安全要点:避免修改正在遍历的结构
for-of本身是只读遍历,但若在循环体内增删Map或Set元素,行为未定义(不同引擎表现可能不同):
- 添加新项:部分引擎会后续遍历到,部分则不会,不可依赖
- 删除当前项:可能跳过下一个元素,或引发迭代中断
- 正确做法:先收集待操作项,循环结束后统一处理
例如需过滤Set中满足条件的元素,应写成const toDelete = [...mySet].filter(...); toDelete.forEach(item => mySet.delete(item));。
兼容性与降级考虑
for-of和Map/Set迭代器在现代环境(ES6+)完全可用。若需支持旧环境:
- 用Babel转译并引入
core-js/stable补丁 - 避免用
for-in遍历Map/Set——它们没有可枚举属性,for-in不会产出任何内容 - 不要尝试用
Array.from()强制转数组再遍历,除非明确需要快照;否则失去流式遍历优势,且增加内存开销


















