标准答案
- 迭代器 iterator 是一个带 next 方法的对象。每次调用 next 都返回 { value, done },done 为 true 表示遍历结束。
- 可迭代对象 iterable 是实现了 Symbol.iterator 方法的对象。这个方法会返回一个迭代器。
- for...of 会先读取对象的 Symbol.iterator,然后不断调用迭代器的 next,直到 done 为 true。数组、字符串、Map、Set 默认都是可迭代对象,所以可以直接 for...of。
- 普通对象默认没有 Symbol.iterator,因此不能直接 for...of。生成器函数 function* 可以用 yield 暂停和恢复执行,它返回的生成器对象本身既是迭代器,也是可迭代对象。
题目解析
for...of 遍历的是可迭代协议产出的值,for...in 遍历的是对象可枚举属性名。数组可以 for...in,但通常不推荐用它遍历数组值。
扩展运算符、数组解构、new Map(entries)、Promise.all(iterable) 等语法或 API 都会消费可迭代对象。理解迭代协议后,这些行为就能串起来。
生成器适合按需产出序列。它不会一次性把所有值都创建出来,而是执行到 yield 时暂停,下次 next 时继续。
代码示例
下面示例先手写可迭代对象,再用生成器函数简化同样的序列产出。
JavaScript
const range = {
start: 1,
end: 3,
[Symbol.iterator]() {
let current = this.start
const end = this.end
return {
next() {
if (current <= end) {
return { value: current++, done: false }
}
return { value: undefined, done: true }
}
}
}
}
[...range] // [1, 2, 3]
function* createRange(start, end) {
for (let value = start; value <= end; value += 1) {
yield value
}
}
[...createRange(1, 3)] // [1, 2, 3]常见误区
- 误以为所有对象都能 for...of。
- 把 iterator 的 next 返回值写成普通 value,漏掉 done。
- 混淆 generator 函数和普通函数。