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