一、ES5 数组遍历方法
1. forEach()
作用:对数组的每个元素执行一次给定的函数
特点:
- 没有返回值
- 不能中途退出循环(没有break功能)
- 会跳过空位(sparse array)
应用场景:当需要对数组每个元素执行操作且不需要返回值时
javascript
const arr = [1, 2, 3];
arr.forEach(function(item, index, array) {
console.log(item, index);
// 输出:
// 1 0
// 2 1
// 3 2
});
2. map()
作用:创建一个新数组,其结果是该数组中的每个元素调用一次提供的函数后的返回值
特点:
- 返回新数组,不改变原数组
- 新数组长度与原数组相同
应用场景:数据转换/格式化
javascript
const numbers = [1, 2, 3];
const doubled = numbers.map(function(num) {
return num * 2;
});
console.log(doubled); // [2, 4, 6]
3. filter()
作用:创建一个新数组,包含通过所提供函数测试的所有元素
特点:
- 返回新数组
- 新数组长度 ≤ 原数组长度
应用场景:数据筛选
javascript
const numbers = [1, 2, 3, 4, 5];
const evens = numbers.filter(function(num) {
return num % 2 === 0;
});
console.log(evens); // [2, 4]
4. reduce()
作用:对数组中的每个元素执行一个reducer函数,将其结果汇总为单个返回值
特点:
- 可以初始化累加器
- 功能强大,可以实现很多其他数组方法
应用场景:数据聚合、统计
javascript
const numbers = [1, 2, 3, 4];
const sum = numbers.reduce(function(accumulator, current) {
return accumulator + current;
}, 0);
console.log(sum); // 10
5. reduceRight()
作用:与reduce类似,但从右向左执行
特点:
- 执行方向与reduce相反
- 适用于需要考虑顺序的场景
应用场景:从右向左的计算
javascript
const arr = ['a', 'b', 'c'];
const rightToLeft = arr.reduceRight(function(acc, cur) {
return acc + cur;
});
console.log(rightToLeft); // 'cba'
6. some()
作用:测试数组中是否至少有一个元素通过了提供的函数的测试
特点:
- 返回布尔值
- 遇到第一个满足条件的元素立即返回true
应用场景:检查数组中是否存在符合条件的元素
javascript
const numbers = [1, 2, 3, 4, 5];
const hasEven = numbers.some(function(num) {
return num % 2 === 0;
});
console.log(hasEven); // true
7. every()
作用:测试数组中的所有元素是否都通过了提供的函数的测试
特点:
- 返回布尔值
- 遇到第一个不满足条件的元素立即返回false
应用场景:验证数组所有元素是否符合条件
javascript
const numbers = [2, 4, 6, 8];
const allEven = numbers.every(function(num) {
return num % 2 === 0;
});
console.log(allEven); // true
8. find() (ES6方法,但在此一并介绍)
作用:返回数组中满足提供的测试函数的第一个元素的值
特点:
- 找到第一个匹配项后立即返回
- 找不到返回undefined
应用场景:查找数组中的特定元素
javascript
const users = [
{id: 1, name: 'Alice'},
{id: 2, name: 'Bob'},
{id: 3, name: 'Charlie'}
];
const user = users.find(function(user) {
return user.id === 2;
});
console.log(user); // {id: 2, name: 'Bob'}
9. findIndex() (ES6方法)
作用:返回数组中满足提供的测试函数的第一个元素的索引
特点:
- 找到第一个匹配项后立即返回其索引
- 找不到返回-1
应用场景:查找元素在数组中的位置
javascript
const numbers = [5, 12, 8, 130, 44];
const index = numbers.findIndex(function(num) {
return num > 10;
});
console.log(index); // 1
二、ES6+ 数组遍历方法
1. for...of 循环
作用:创建迭代循环,遍历可迭代对象(包括数组)
特点:
- 简洁语法
- 可以直接获取值而非索引
- 可以使用break和continue
应用场景:需要中断的循环或需要直接获取值的场景
javascript
const arr = ['a', 'b', 'c'];
for (const item of arr) {
if (item === 'b') break;
console.log(item); // 'a'
}
2. entries()
作用:返回一个新的数组迭代器对象,包含数组中每个索引的键/值对
特点:
- 返回迭代器而非数组
- 可以与for...of配合使用
应用场景:需要同时获取索引和值的遍历
javascript
const arr = ['a', 'b', 'c'];
for (const [index, element] of arr.entries()) {
console.log(index, element);
// 0 'a'
// 1 'b'
// 2 'c'
}
3. keys()
作用:返回一个新的数组迭代器对象,包含数组中每个索引的键
特点:
- 只返回索引
- 可以与for...of配合使用
应用场景:只需要索引的遍历
javascript
const arr = ['a', 'b', 'c'];
for (const key of arr.keys()) {
console.log(key); // 0, 1, 2
}
4. values()
作用:返回一个新的数组迭代器对象,包含数组中每个索引的值
特点:
- 只返回值
- 可以与for...of配合使用
应用场景:只需要值的遍历
javascript
const arr = ['a', 'b', 'c'];
for (const value of arr.values()) {
console.log(value); // 'a', 'b', 'c'
}
5. flatMap() (ES2019)
作用:首先使用映射函数映射每个元素,然后将结果压缩成一个新数组
特点:
- map()和flat()的组合
- 只能展开一层
应用场景:映射后需要展平的场景
javascript
const arr = [1, 2, 3];
const result = arr.flatMap(x => [x, x * 2]);
console.log(result); // [1, 2, 2, 4, 3, 6]
三、性能比较与选择建议
方法 | 中断能力 | 返回值 | 适用场景 |
---|---|---|---|
for循环 | 可以 | 无 | 需要最高性能或需要中断 |
forEach() | 不可以 | 无 | 简单遍历,不需要中断 |
map() | 不可以 | 新数组 | 数据转换 |
filter() | 不可以 | 新数组 | 数据筛选 |
reduce() | 不可以 | 单个值 | 数据聚合 |
some() | 可以 | 布尔值 | 存在性检查 |
every() | 可以 | 布尔值 | 全体验证 |
find() | 可以 | 元素 | 查找元素 |
findIndex() | 可以 | 索引 | 查找位置 |
for...of | 可以 | 无 | 需要中断或简洁语法 |
四、特殊场景处理
1. 稀疏数组处理
javascript
const sparseArray = [1, , 3]; // 注意中间的空位
// forEach会跳过空位
sparseArray.forEach(function(item) {
console.log(item); // 1, 3
});
// map会保留空位
const mapped = sparseArray.map(function(item) {
return item * 2;
});
console.log(mapped); // [2, empty, 6]
2. 异步处理
javascript
// 使用for...of处理异步
async function processArray(array) {
for (const item of array) {
await doSomethingAsync(item);
}
}
// 使用Promise.all配合map处理并行异步
async function processInParallel(array) {
await Promise.all(array.map(async item => {
await doSomethingAsync(item);
}));
}
3. 提前终止循环的技巧
javascript
// 使用some实现提前终止
const arr = [1, 2, 3, 4];
arr.some(item => {
console.log(item);
if (item === 3) return true; // 相当于break
});
// 使用every实现提前终止
arr.every(item => {
console.log(item);
if (item === 3) return false; // 相当于break
return true;
});
五、总结
JavaScript 提供了多种数组遍历方法,每种方法都有其特定的用途:
- 简单遍历 :
forEach
、for...of
- 数据转换 :
map
、flatMap
- 数据筛选 :
filter
- 数据聚合 :
reduce
、reduceRight
- 存在性检查 :
some
、every
- 元素查找 :
find
、findIndex
- 索引/值遍历 :
entries
、keys
、values
选择合适的方法可以使代码更简洁、更易读,同时也能提高性能。在实际开发中,应根据具体需求选择最适合的遍历方法。