js for in 和 for of 的区别

553 阅读2分钟

在 JavaScript 中,for...in 和 for...of 是两种不同的循环语法,它们的用途和适用场景有明显区别:

1. for...in

  • 用途:遍历对象的可枚举属性(包括自身属性和原型链上的属性)。

  • 适用对象:普通对象(Object)。

  • 遍历内容:对象的 键(key) ,即属性名。

  • 特点

    • 会遍历对象的所有可枚举属性,包括继承的属性(可通过 hasOwnProperty 过滤)。
    • 遍历数组时,返回的是数组的索引(字符串形式),但可能遍历到非数字属性(如手动添加的属性)。
    • 不保证遍历顺序(尤其是对复杂对象)。
const obj = { a: 1, b: 2 };
for (const key in obj) {
  console.log(key); // 输出 "a", "b"
}

// 遍历数组(不推荐!)
const arr = [10, 20, 30];
arr.foo = "bar";
for (const index in arr) {
  console.log(index); // 输出 "0", "1", "2", "foo"
}

2. for...of

  • 用途:遍历可迭代对象(Iterable)  的值。

  • 适用对象:数组、字符串、MapSetarguments 等实现了 Symbol.iterator 接口的对象。

  • 遍历内容:对象的 值(value)

  • 特点

    • 直接获取值,无需通过索引访问。
    • 不会遍历原型链上的属性。
    • 不适用于普通对象(除非对象实现了 Symbol.iterator)。
const arr = [10, 20, 30];
arr.foo = "bar";
for (const value of arr) {
  console.log(value); // 输出 10, 20, 30(不会遍历到 "foo")
}

// 遍历字符串
const str = "hello";
for (const char of str) {
  console.log(char); // 输出 "h", "e", "l", "l", "o"
}

关键区别总结

特性for...infor...of
遍历目标对象的可枚举属性名(键)可迭代对象的值(value)
适用对象普通对象、数组(不推荐)数组、字符串、Map、Set 等可迭代对象
遍历内容键(字符串)
原型链属性会遍历不会遍历
顺序保证不保证(因对象而异)按迭代器定义的顺序
普通对象是否支持支持不支持(除非实现迭代器)

使用建议

  • 遍历对象属性:用 for...in(配合 hasOwnProperty 过滤原型链属性)。
  • 遍历数组或可迭代对象的值:用 for...of
  • 不要用 for...in 遍历数组:可能引发意外行为(如遍历到非数字属性)。
// 正确遍历数组
const arr = [1, 2, 3];
for (const value of arr) {
  console.log(value); // 1, 2, 3
}

// 正确遍历对象
const obj = { a: 1, b: 2 };
for (const key in obj) {
  if (obj.hasOwnProperty(key)) {
    console.log(key, obj[key]); // a 1, b 2
  }
}