for/for in/for of/foreach/map/set

40 阅读1分钟

1. for...in vs for...of

  • for...in:遍历对象键名(包括原型链属性),不保证顺序。
    const obj = { a: 1, b: 2 };
    for (const key in obj) {
      console.log(key); // 输出: "a", "b"
    }
    
  • for...of:遍历可迭代对象的值(如数组、字符串、Set),支持 break
    const arr = ['x', 'y'];
    for (const value of arr) {
      console.log(value); // 输出: "x", "y"
    }
    

2. forEach vs map

  • forEach:无返回值,纯副作用(修改原数组或执行操作)。
    const arr = [1, 2];
    arr.forEach((num, i) => arr[i] = num * 2);
    console.log(arr); // [2, 4]
    
  • map:返回新数组,不修改原数组。
    const arr = [1, 2];
    const doubled = arr.map(num => num * 2);
    console.log(doubled); // [2, 4]
    

3. Set 和 Map 的特性

  • Set:数组去重,无索引,支持 adddeletehas
    const set = new Set([1, 2, 2]);
    console.log(set.size); // 2
    
  • Map:存储键值对,键可为任意类型(对象、函数等)。
    const map = new Map();
    const key = {};
    map.set(key, 'value');
    console.log(map.get(key)); // "value"
    

4. 循环中断方式

  • 可中断forfor...of(使用 breakcontinue)。
  • 不可中断forEachmap(无法提前终止)。
    替代方案
    // 使用 some/every 模拟中断
    arr.some(item => {
      if (item > 10) return true; // 中断条件
      console.log(item);
      return false;
    });
    

5. 性能对比(从快到慢)

for > for...of > forEach > for...in
  • for:直接操作索引,适合大量数据。
  • for...in:最慢(需处理原型链,类型转换),仅用于对象。

6. 问答

  • 问:如何正确遍历对象属性?

    // 方法1:for...in + hasOwnProperty
    for (const key in obj) {
      if (obj.hasOwnProperty(key)) {
        console.log(key);
      }
    }
    
    // 方法2:Object.keys/entries
    Object.entries(obj).forEach(([key, value]) => {
      console.log(key, value);
    });
    
  • 问:Set 和 Array 的区别?

    • Set:元素唯一,无索引,插入/查找效率高(O(1)),适合去重。
    • Array:可重复,有索引,支持排序、切片等操作。