在 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) 的值。
-
适用对象:数组、字符串、
Map
、Set
、arguments
等实现了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...in | for...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
}
}