简述ES6规定for…in 和for…of有什么区别?
参考回答
for...in 和 for...of 是 ES6 中两种用于遍历的语法,但它们的适用场景和行为存在明显区别:
for...in:用来遍历对象的可枚举属性(包括继承的属性)。- 适合用于遍历对象的属性名。
- 返回的是键名,不适合用于遍历数组的元素。
示例:
const obj = { a: 1, b: 2, c: 3 }; for (const key in obj) { console.log(key); // 输出: 'a', 'b', 'c' }for...of:用来遍历可迭代对象(Iterable),如数组、字符串、Set、Map 等。- 返回的是值,适合用于遍历数组或其他可迭代对象。
- 无法直接用于普通对象,因为对象不是默认的可迭代对象。
示例:
const array = [10, 20, 30]; for (const value of array) { console.log(value); // 输出: 10, 20, 30 }
详细讲解与拓展
1. 适用范围的区别
| 特性 | for...in |
for...of |
|---|---|---|
| 遍历目标 | 对象的可枚举属性(键名) | 可迭代对象(Iterable)的值 |
| 遍历范围 | 包括原型链上的属性 | 仅遍历自身的值 |
| 遍历结果 | 键名(字符串或 Symbol) | 值 |
| 数据结构支持 | 对象和数组,但不建议用于数组 | 数组、字符串、Set、Map 等 |
2. for...in 的特点
- 返回键名:
遍历的结果是对象或数组的键名(索引或属性名)。const arr = [1, 2, 3]; for (const key in arr) { console.log(key); // 输出: 0, 1, 2 } - 包括继承属性:
for...in会枚举出对象原型链上的属性。const obj = Object.create({ inheritedProp: 'value' }); obj.ownProp = 'ownValue'; for (const key in obj) { console.log(key); // 输出: 'inheritedProp', 'ownProp' } - 适合对象属性遍历:
常用于遍历普通对象的属性,但需要结合hasOwnProperty检查是否是自身属性:for (const key in obj) { if (obj.hasOwnProperty(key)) { console.log(key); // 仅输出对象自身的属性 } } - 不适合遍历数组:
对于数组,for...in返回的是索引,且可能因为数组的原型被修改而导致意外行为,不建议使用。
3. for...of 的特点
-
返回值:
for...of遍历的是可迭代对象的值,而不是键名。const arr = [1, 2, 3]; for (const value of arr) { console.log(value); // 输出: 1, 2, 3 } - 仅作用于可迭代对象:
for...of遍历的是实现了Symbol.iterator方法的对象,例如:- 数组
- 字符串
- Set
- Map
- Generator 函数
普通对象不能直接用于
for...of,会报错:const obj = { a: 1, b: 2 }; for (const value of obj) { console.log(value); // TypeError: obj is not iterable } - 不包括原型链属性:
for...of不会涉及对象的原型链。 -
应用场景:
用于处理数组或其他可迭代对象,尤其适合需要直接获取值的场景:const map = new Map([['a', 1], ['b', 2]]); for (const [key, value] of map) { console.log(key, value); // 输出: 'a' 1, 'b' 2 }
4. 两者的对比示例
对同一对象或数组的遍历效果:
const arr = [10, 20, 30];
const obj = { a: 1, b: 2 };
console.log('for...in 遍历数组:');
for (const key in arr) {
console.log(key); // 输出: 0, 1, 2
}
console.log('for...of 遍历数组:');
for (const value of arr) {
console.log(value); // 输出: 10, 20, 30
}
console.log('for...in 遍历对象:');
for (const key in obj) {
console.log(key); // 输出: 'a', 'b'
}
// for...of 无法直接用于对象
5. 使用建议
for...in:- 主要用于遍历对象的属性。
- 需结合
hasOwnProperty避免遍历到继承的属性。 - 不建议用于数组的遍历。
for...of:- 适合用于遍历数组、字符串、Set、Map 等可迭代对象。
- 更适合处理元素值的场景,而不是键名。
- 如果需要遍历对象,可以通过
Object.entries()将对象转为可迭代的键值对数组:
for (const [key, value] of Object.entries(obj)) { console.log(key, value); }
总结
for...in遍历的是键名,适合用于对象属性的枚举,但包括原型链上的属性,需注意筛选。for...of遍历的是值,适用于所有实现了Symbol.iterator的可迭代对象,如数组、字符串、Set 和 Map,无法直接作用于普通对象。
掌握两者的适用场景,能让代码更高效、更语义化。