面试题:JavaScript 中 for…in 和 for…of 的区别是什么?

这是一个非常经典的 JavaScript 面试题,考察对循环机制和数据结构的理解。for...infor...of 看似相似,但用途和行为有本质区别。


✅ 核心区别总结

特性for...infor...of
设计目的遍历对象的可枚举属性(键)遍历可迭代对象
适用对象所有对象(包括数组、普通对象)仅限可迭代对象(Array, Map, Set, String, arguments, TypedArray 等)
遍历内容属性的 键名(字符串)可迭代对象的
原型链遍历自身 + 原型链上的可枚举属性仅遍历对象自身的可迭代数据(不包括原型)
可迭代协议不要求实现 Symbol.iterator要求实现 Symbol.iterator 接口

🔍 详细对比与示例

1. 遍历数组

const arr = [10, 20, 30];

// for...in:遍历的是索引(字符串类型)
for (let key in arr) {
  console.log(key); // "0", "1", "2"
  console.log(typeof key); // string
}

// for...of:遍历的是元素值
for (let value of arr) {
  console.log(value); // 10, 20, 30
}

⚠️ 注意:for...in 遍历数组时,索引是字符串,且可能受原型污染影响。

2. 遍历普通对象

const obj = { a: 1, b: 2 };

// for...in:✅ 可以遍历对象的键
for (let key in obj) {
  console.log(key);     // "a", "b"
  console.log(obj[key]); // 1, 2
}

// for...of:❌ 报错,因为普通对象不是可迭代的
for (let value of obj) {
  // TypeError: obj is not iterable
}

✅ 正确做法:用 Object.keys(obj)Object.values()Object.entries() 配合 for...of

for (let [key, value] of Object.entries(obj)) {
  console.log(key, value); // "a" 1, "b" 2
}

3. 遍历字符串

const str = "hi";

for (let char of str) {
  console.log(char); // "h", "i"
}

for (let index in str) {
  console.log(index); // "0", "1"
}

4. 原型链影响

Array.prototype.customMethod = function() {};

const arr = [1, 2, 3];

for (let key in arr) {
  console.log(key); // "0", "1", "2", "customMethod" ❌
}

for (let value of arr) {
  console.log(value); // 1, 2, 3 ✅(不受原型方法影响)
}

for...in 会遍历到原型链上的可枚举属性,容易出 bug。


✅ 使用建议

  • 遍历数组/可迭代对象的值 → 优先使用 for...of
  • 遍历对象的属性键 → 使用 for...in(但注意 hasOwnProperty 判断)
  • 遍历对象的值或键值对 → 推荐 Object.keys/values/entries() + for...of
  • ❌ 不要用 for...in 遍历数组的值(易出错)

💡 面试回答模板

for...in 主要用于遍历对象的可枚举属性名(键),包括原型链上的属性,适合遍历普通对象。而 for...of 是 ES6 引入的,用于遍历实现了 Symbol.iterator 接口的可迭代对象(如数组、Map、Set 等),直接获取的是元素的值。

它不适用于普通对象,除非对象本身定义了迭代器。因此,for...of 更安全、更直观,推荐在遍历数组或集合时使用。

THE END
喜欢就支持一下吧
点赞6 分享