简述ES6规定for…in 和for…of有什么区别?

参考回答

for...infor...of 是 ES6 中两种用于遍历的语法,但它们的适用场景和行为存在明显区别:

  1. for...in:用来遍历对象的可枚举属性(包括继承的属性)。
    • 适合用于遍历对象的属性名。
    • 返回的是键名,不适合用于遍历数组的元素。

    示例:

    const obj = { a: 1, b: 2, c: 3 };
    for (const key in obj) {
     console.log(key); // 输出: 'a', 'b', 'c'
    }
    
  2. 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,无法直接作用于普通对象。

掌握两者的适用场景,能让代码更高效、更语义化。

发表评论

后才能评论