在JavaScript的循环语法中,for...of和for...in都是常用的遍历方式,但两者的设计逻辑和适用场景存在明显差异,很多开发者容易混淆两者的用法,导致遍历结果不符合预期。下面我们就来详细拆解两者的区别。

核心设计目标不同
for...in是早期JavaScript就存在的循环语法,设计初衷是遍历对象的可枚举属性,包括对象自身的可枚举属性和从其原型链上继承的可枚举属性。而for...of是ES6新增的循环语法,设计目标是遍历可迭代对象(Iterable Object)的值,它依赖对象的迭代器实现,只能遍历符合可迭代协议的对象。
遍历数组时的表现差异
先来看遍历普通数组的情况,两者的输出结果完全不同:
const arr = [10, 20, 30];
// 给数组添加一个自定义属性
arr.customProp = 'test';
console.log('for...in遍历数组结果:');
for (const key in arr) {
console.log(key); // 输出:0、1、2、customProp
}
console.log('for...of遍历数组结果:');
for (const value of arr) {
console.log(value); // 输出:10、20、30
}从结果可以看出,for...in遍历数组时拿到的是数组的索引(本质是字符串类型的属性名),还会遍历到数组自定义的属性;而for...of遍历数组时直接拿到数组的元素值,不会遍历自定义属性。
遍历普通对象时的差异
普通对象默认不是可迭代对象,因此for...of无法直接遍历普通对象,会直接抛出错误:
const obj = { name: '张三', age: 25, city: '北京' };
console.log('for...in遍历对象结果:');
for (const key in obj) {
console.log(key, obj[key]); // 输出:name 张三、age 25、city 北京
}
console.log('for...of遍历对象结果:');
try {
for (const value of obj) {
console.log(value);
}
} catch (e) {
console.log(e.message); // 输出:obj is not iterable
}如果要让for...of遍历普通对象,需要先获取对象的键、值或者键值对数组,再使用for...of遍历:
const obj = { name: '张三', age: 25, city: '北京' };
// 遍历对象的键
for (const key of Object.keys(obj)) {
console.log(key); // 输出:name、age、city
}
// 遍历对象的值
for (const value of Object.values(obj)) {
console.log(value); // 输出:张三、25、北京
}
// 遍历对象的键值对
for (const [key, value] of Object.entries(obj)) {
console.log(key, value); // 输出:name 张三、age 25、city 北京
}遍历其他数据类型的差异
除了数组和对象,两者在遍历字符串、Map、Set等类型时也有明显区别:
- 遍历字符串:for...in会遍历字符串的索引,for...of会遍历字符串的每个字符
- 遍历Map/Set:for...in无法遍历Map和Set的内容,for...of可以直接遍历Map的键值对或者Set的元素
看下面的示例:
const str = 'abc';
const set = new Set([1, 2, 3]);
const map = new Map([['a', 1], ['b', 2]]);
console.log('for...in遍历字符串:');
for (const key in str) {
console.log(key); // 输出:0、1、2
}
console.log('for...of遍历字符串:');
for (const char of str) {
console.log(char); // 输出:a、b、c
}
console.log('for...of遍历Set:');
for (const item of set) {
console.log(item); // 输出:1、2、3
}
console.log('for...of遍历Map:');
for (const [key, value] of map) {
console.log(key, value); // 输出:a 1、b 2
}使用注意事项
- for...in遍历对象时,如果只需要遍历对象自身的可枚举属性,建议使用
hasOwnProperty方法过滤原型链上的属性,避免拿到不需要的属性。 - 遍历数组时优先使用for...of,除非明确需要拿到数组的索引或者自定义属性,否则不要用for...in遍历数组,避免逻辑错误。
- for...of只能遍历可迭代对象,判断一个对象是否可迭代可以查看该对象是否有
Symbol.iterator属性。
总结来说,for...in适合遍历对象的属性,for...of适合遍历可迭代对象的值,根据遍历的目标数据类型选择合适的循环方式,能减少很多不必要的bug。
for...offor...inJavaScript遍历迭代器修改时间:2026-06-05 02:12:33