在前端开发中,我们经常需要对数组、对象或其他可遍历结构进行循环。JavaScript 提供了多种方式,其中最容易混淆的就是 for...in
和 for...of
,真的很难记。它们看起来很像,但本质上完全不同,作用对象和遍历内容也大不一样。本篇文章将带你系统地了解它们之间的区别与使用场景。
语法
for…in
用于遍历对象的可枚举属性(包括原型链上的)
1 2 3 4
| const obj = { a: 1, b: 2 }; for (let key in obj) { console.log(key); }
|
for…of
用于遍历可迭代对象(iterable)的元素(如数组、字符串、Set、Map 等)
1 2 3 4
| const arr = ['x', 'y', 'z']; for (let value of arr) { console.log(value); }
|
适用对象
类型 |
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); }
for (let val of arr) { console.log(val); }
|
原型链属性
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); }
for (let key of Object.keys(obj)) { console.log(key); }
|
💡 若使用 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); }
|
适用场景
场景 |
建议使用 |
遍历对象的属性(包括可能的动态属性) |
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