这是一个常见的面试题,考察对 JavaScript 迭代机制的理解。
核心答案:
普通的 JavaScript 对象(Object)默认是不可迭代的,因此不能直接使用
for...of
遍历。 但可以通过一些方法使其支持for...of
。
❌ 为什么不能直接用 for...of
遍历普通对象?
for...of
只能遍历实现了 [Symbol.iterator] 接口的可迭代对象(如:Array、Map、Set、String、arguments 等)。
普通对象没有实现 Symbol.iterator
,所以直接使用会报错:
const obj = { a: 1, b: 2, c: 3 };
for (const item of obj) {
console.log(item);
}
// ❌ 报错:obj is not iterable
✅ 正确的方法:如何用 for...of
遍历对象?
方法一:遍历对象的 可迭代视图(推荐)
使用 Object.keys()
、Object.values()
或 Object.entries()
,它们返回数组,是可迭代的:
const obj = { a: 1, b: 2, c: 3 };
// 遍历键
for (const key of Object.keys(obj)) {
console.log(key); // 'a', 'b', 'c'
}
// 遍历值
for (const value of Object.values(obj)) {
console.log(value); // 1, 2, 3
}
// 遍历键值对
for (const [key, value] of Object.entries(obj)) {
console.log(key, value); // 'a' 1, 'b' 2, 'c' 3
}
方法二:手动添加 Symbol.iterator
(高级用法)
可以让对象变成可迭代对象:
const obj = { a: 1, b: 2, c: 3 };
// 添加迭代器
obj[Symbol.iterator] = function* () {
const entries = Object.entries(this);
for (const [key, value] of entries) {
yield [key, value]; // 或 yield value
}
};
// 现在可以用 for...of 了
for (const [key, value] of obj) {
console.log(key, value); // 'a' 1, 'b' 2, 'c' 3
}
⚠️ 注意:这种方法修改了对象本身,一般不推荐用于生产环境,除非你明确控制该对象。
🔁 对比:for...in
vs for...of
特性 | for...in | for...of |
---|---|---|
遍历对象 | ✅ 可以(遍历可枚举属性) | ❌ 默认不行 |
遍历数组 | ✅ 但遍历的是索引(字符串) | ✅ 遍历的是元素值 |
原型链 | 包含原型上的可枚举属性 | 只遍历对象自身的可迭代数据 |
可迭代性 | 不要求可迭代 | 要求对象实现 Symbol.iterator |
✅ 最佳实践总结
- 不要对普通对象直接使用
for...of
。 - 使用
Object.keys/values/entries()
+for...of
是最安全、最常用的方式。 - 如果需要自定义迭代行为,可以实现
Symbol.iterator
,但要谨慎使用。
所以,回答面试题时可以说:
“for...of
不能直接遍历普通对象,因为对象不是可迭代对象。但我们可以使用Object.values(obj)
或Object.entries(obj)
等方法获取可迭代结构,再用for...of
遍历。”
THE END