javascript迭代器是什么_for of循环怎么使用?

17次阅读

for…of 是专为可迭代对象设计的语法糖,要求对象实现 symbol.iterator 方法并返回合法迭代器;普通对象默认不可迭代,需手动实现;常见可迭代对象包括 ArrayString、Set、map、TypedArray、arguments 和 nodeList。

javascript迭代器是什么_for of循环怎么使用?

for...of 循环不是“遍历数组的另一种写法”,它是专门面向可迭代对象(iterable) 的语法糖——只要一个对象实现了 Symbol.iterator 方法并返回合法迭代器,它就能被 for...of 消费。普通对象(如 {a: 1, b: 2})默认不满足这个条件,直接用会报 TypeError: xxx is not iterable

哪些值能直接用 for...of

常见可迭代对象包括:ArrayStringSetMapTypedArrayargumentsNodeList(如 document.querySelectorAll() 返回值)。它们原生支持迭代协议。

  • Array:按索引顺序取值
  • String:按 Unicode 码点逐字符遍历(注意:代理对如 emoji 可能被拆开)
  • Map:每次迭代返回 [key, value] 数组,需用解构 for (const [k, v] of map)
  • Set:只返回元素值,无重复、无索引
  • NodeList:可直接遍历 dom 节点,无需转成数组
const list = document.querySelectorAll('p'); for (const p of list) {   p.style.color = 'blue'; }

想让普通对象也能 for...of 怎么办?

必须手动实现 Symbol.iterator。这不是“加个方法就行”,它得返回一个符合规范的迭代器对象(即有 next() 方法,且返回 { value, done } 形式)。

  • 不能只写 obj[Symbol.iterator] = () => ({}) —— 缺少 next 会报错
  • 若只想遍历自身可枚举属性值,可用 Object.values(this) 构造迭代器
  • 注意:for...in 遍历的是键名,for...of 遍历的是你定义的 value,二者语义完全不同
const obj = { a: 1, b: 2 }; obj[Symbol.iterator] = function* () {   for (const key of Object.keys(this)) {     yield this[key];   } }; for (const val of obj) console.log(val); // 1, 2

为什么不用 for...in 替代?

for...in 是为遍历对象属性设计的,它会:

  • 遍历所有可枚举属性(包括原型链上的)
  • 不保证顺序(尤其在老引擎中)
  • 返回的是键名(string),不是值

for...of 的目标是**数据消费**,强调顺序、可控性与一致性。比如遍历 Map 时,for...in 根本不会进入循环(因为 Map 不是普通对象,没有可枚举属性),但 for...of 天然支持。

更关键的是:当你写 for (const item of arr),你明确表达“我要处理每个元素”;而 for (const i in arr) 其实是在说“我要检查每个索引键”,语义错位容易引发 bug(比如误把数组方法当元素)。

立即学习Java免费学习笔记(深入)”;

常见翻车点和替代方案

遇到 TypeError: xxx is not iterable 别急着查文档,先确认三件事:

  • 你操作的对象是否真的实现了 Symbol.iteratortypeof xxx[Symbol.iterator] 应为 "function"
  • 是否误把 undefinedNULL 当作可迭代对象传入?
  • 是否在异步场景下用了同步 for...of?此时应改用 for await...of(如遍历 AsyncIterator

如果只是想带索引遍历数组,别手写计数器,优先用:arr.entries()

const arr = ['a', 'b', 'c']; for (const [i, val] of arr.entries()) {   console.log(i, val); // 0 'a', 1 'b', 2 'c' }

真正难的不是语法,而是判断“这个东西到底算不算可迭代”——它取决于协议,不是类型。很多开发者卡在这里,是因为把 for...of 当成“高级 for 循环”,其实它是数据契约的体现:你提供迭代器,我负责消费。

text=ZqhQzanResources