前端数组遍历该用什么方法?带你一探究竟!

26 阅读4分钟

1. 基本for循环

for (let i = 0; i < arr.length; i++) {
  // 操作 arr[i]
}

优点:

  • 性能最优(尤其在大型数组操作时)
  • 可控制循环流程(break, continue, return)
  • 可访问索引,便于复杂操作
  • 兼容性最好(所有浏览器和Node.js版本)

缺点:

  • 代码冗长,容易出错
  • 需要手动处理边界条件
  • 可读性较差

适用场景:

  • 性能关键的大数据量处理
  • 需要精细控制循环流程时
  • 需要同时访问多个数组时
  • 不支持ES5的老旧环境

2. for...of循环(ES6)

for (const item of arr) {
  // 操作 item
}

优点:

  • 简洁直观,语法清晰
  • 可遍历可迭代对象(包括Map, Set等)
  • 支持break, continue, return
  • 避免索引操作的复杂性

缺点:

  • 无法直接获取索引(需配合entries())
  • 不支持异步操作
  • 性能略低于传统for循环

适用场景:

  • 只需要值而不需要索引时

  • 遍历各种可迭代对象

  • 需要简洁语法且要控制流程时

3. forEach方法

arr.forEach((item, index, array) => {
  // 操作
});

优点:

  • 语义清晰,函数式风格
  • 自动提供值和索引
  • 回调函数内this可绑定

缺点:

  • 无法中断循环(不能break/return跳出)
  • 不支持异步(无法用async/await)
  • 性能稍差于for循环

适用场景:

  • 简单遍历,不需要中断操作
  • 链式调用(结合map/filter等)
  • 强调声明式编程的场景

4. map方法

const newArr = arr.map((item, index, array) => {
  return item * 2;
});

优点:

  • 函数式编程,无副作用
  • 自动返回新数组
  • 代码简洁易读

缺点:

  • 始终返回新数组,内存开销大
  • 无法中断循环
  • 性能较低(相比for循环)

适用场景:

  • 需要转换数组元素并返回新数组
  • 数据映射操作
  • React/Vue中的列表渲染

5. filter方法

const filtered = arr.filter((item, index, array) => {
  return item > 10;
});

优点:

  • 专门用于筛选,语义明确
  • 返回新数组,不改变原数组

缺点:

  • 只能用于筛选场景
  • 性能开销(创建新数组)

适用场景:

  • 从数组中筛选符合条件的元素
  • 结合map/reduce进行数据处理

6. reduce/reduceRight

const sum = arr.reduce((accumulator, current, index, array) => {
  return accumulator + current;
}, initialValue);

优点:

  • 功能强大,可实现复杂聚合操作
  • 返回任意类型结果
  • 支持从右向左遍历(reduceRight)

缺点:

  • 学习曲线较陡
  • 可读性较差(复杂逻辑时)

适用场景:

  • 数组聚合计算(求和、平均值等)
  • 数组转对象或Map
  • 实现复杂的数据转换

7. some/every

const hasLarge = arr.some(item => item > 10);
const allPositive = arr.every(item => item > 0);

优点:

  • 语义明确,用于条件检测
  • 可提前终止(找到结果即停止)

缺点:

  • 功能单一,仅用于条件检查

适用场景:

  • 检查数组中是否存在/全部满足条件的元素
  • 数据验证

8. for...in循环(不推荐用于数组)

for (const index in arr) {
  // 注意:index是字符串,可能遍历到原型链属性
}

缺点:

  • 会遍历继承的可枚举属性
  • 遍历顺序不确定
  • index为字符串类型
  • 性能较差

建议:避免用于数组遍历,仅用于对象遍历

9. find/findIndex

const item = arr.find(item => item.id === 5);
const index = arr.findIndex(item => item.id === 5);

优点:

  • 语义明确,查找特定元素
  • 找到即停止,性能较好

缺点:

  • 仅用于查找场景

适用场景:

  • 查找符合条件的第一项元素

  • 替代indexOf(复杂条件时)

性能对比(基准测试结果)

  • 基本for循环 ≈ for...of循环 > forEach > map/filter > reduce
  • 小型数组差异可忽略不计
  • 大型数组(>10万)推荐使用基本for循环或for...of

使用建议总结

1. 根据需求选择

  • 需要中断/控制流程 → for、for...of
  • 需要新数组 → map、filter
  • 需要聚合计算 → reduce
  • 需要查找元素 → find、some、every
  • 简单遍历无中断 → forEach

2. 性能优先场景

// 性能关键的大数组操作
for (let i = 0; i < largeArray.length; i++) {
  // 密集计算
}

// 或使用while循环(性能最好)
let i = largeArray.length;
while (i--) {
  // 操作
}

3. 可读性优先场景

// 数据处理管道
const result = array
  .filter(item => item.active)
  .map(item => ({ ...item, score: calculateScore(item) }))
  .sort((a, b) => b.score - a.score);

4. 异步遍历

// 使用for...of配合await
for (const item of array) {
  await processItem(item);
}

// 或使用for循环
for (let i = 0; i < array.length; i++) {
  await processItem(array[i]);
}

5. 现代最佳实践组合

// 1. 普通遍历:for...of
for (const user of users) {
  console.log(user.name);
}

// 2. 数据转换:map/filter/reduce
const activeUserNames = users
  .filter(user => user.isActive)
  .map(user => user.name);

// 3. 条件检查:some/every
const hasAdmin = users.some(user => user.role === 'admin');

// 4. 性能敏感:传统for循环
for (let i = 0; i < 1000000; i++) {
  // 高性能计算
}

总结概览

在这里插入图片描述

最佳实践总结:

  • 90%的场景:优先使用map、filter、find、some等高阶函数,它们更声明式、更安全
  • 需要中断循环时:使用for...of或传统for循环
  • 性能关键路径:使用传统for循环
  • 遍历可迭代对象:使用for...of
  • 简单的副作用操作:考虑forEach,但注意其无法中断
  • 避免在forEach中使用async/await,需要并行处理时考虑Promise.all

在这里插入图片描述