for...in与for...of

  在前端开发中,我们经常需要对数组、对象或其他可遍历结构进行循环。JavaScript 提供了多种方式,其中最容易混淆的就是 for...infor...of,真的很难记。它们看起来很像,但本质上完全不同,作用对象和遍历内容也大不一样。本篇文章将带你系统地了解它们之间的区别与使用场景。

语法

for…in

用于遍历对象的可枚举属性(包括原型链上的)

1
2
3
4
const obj = { a: 1, b: 2 };
for (let key in obj) {
console.log(key); // 输出 'a' 和 'b'
}

for…of

用于遍历可迭代对象(iterable)的元素(如数组、字符串、Set、Map 等)

1
2
3
4
const arr = ['x', 'y', 'z'];
for (let value of arr) {
console.log(value); // 输出 'x'、'y'、'z'
}

适用对象

类型 for...in for...of
对象 Object ✅ 是 ❌ 否
数组 Array ✅ 是(索引) ✅ 是(值)
字符串 String ✅ 是(索引) ✅ 是(字符)
Map ❌ 否 ✅ 是(键值对)
Set ❌ 否 ✅ 是(值)
类数组对象 ✅ 是 ✅ 是(如果实现了迭代器)

tips:我一般把这个in直接记成index,也就是对应着对象里的key了

具体区别

遍历内容

  • for...in 遍历的是“键(属性名)
  • for...of 遍历的是“值(元素内容)
1
2
3
4
5
6
7
8
9
const arr = ['a', 'b', 'c'];

for (let i in arr) {
console.log(i); // 0, 1, 2(索引)
}

for (let val of arr) {
console.log(val); // a, b, c(值)
}

原型链属性

  • for...in 会枚举继承自原型链的可枚举属性
  • for...of 只遍历自身的数据,不理会原型链
1
2
3
4
5
6
7
8
9
10
const obj = { x: 1 };
Object.prototype.y = 2;

for (let key in obj) {
console.log(key); // x, y(原型属性也会被枚举)
}

for (let key of Object.keys(obj)) {
console.log(key); // x
}

💡 若使用 for...in,一般要搭配 hasOwnProperty() 过滤原型属性。

可迭代性要求

  • for...of 要求被遍历的对象实现了 Symbol.iterator 接口。
  • 纯普通对象默认不具备可迭代性,不能用 for...of 遍历。
1
2
3
4
5
6
7
const obj = { a: 1, b: 2 };

for (let key in obj) {
console.log(key); // a, b
}

// for (let val of obj) 这样会报错:obj is not iterable

适用场景

场景 建议使用
遍历对象的属性(包括可能的动态属性) for...in(注意过滤原型)
遍历数组元素 for...of / forEach
遍历 Map 或 Set for...of
要遍历值并能中断循环(支持 break) for...of
1
2
3
4
5
6
7
8
9
10
11
12
13
const obj = { name: 'Tom', age: 18 };

// 遍历键值对
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
console.log(key, obj[key]);
}
}

// 更安全的方式
for (let [key, value] of Object.entries(obj)) {
console.log(key, value);
}

小结

  • for...in:用来遍历对象的键,适用于对象属性操作。
  • for...of:用来遍历可迭代对象的值,更适合数组、Set、Map、字符串等。

简单记法:in 是 key(index),of 是 value

作者

Fu9Zhou

发布于

2025-07-06

许可协议