JavaScript 数组方法详解:map()
、filter()
、find()
、forEach()
这些方法都是对数组进行迭代操作的核心函数,但用途和返回值有本质区别。以下是详细对比:
方法 | 返回值 | 用途 | 是否改变原数组 | 执行次数 |
---|---|---|---|---|
map() | 新数组(同长度) | 对每个元素加工后返回新数组 | ❌ 不改变 | 遍历所有元素 |
filter() | 新数组(子集) | 筛选符合条件的元素组成新数组 | ❌ 不改变 | 遍历所有元素 |
find() | 单个元素 或 undefined | 查找第一个符合条件的元素 | ❌ 不改变 | 找到即停止 |
forEach() | undefined | 遍历数组(用于副作用操作) | ❌ 不改变 | 遍历所有元素 |
1. map()
- 映射数组
用途:对每个元素执行相同操作,返回与原数组长度相同的新数组。
语法:
const newArray = array.map((element, index, array) => { ... });
示例:
const numbers = [1, 2, 3];
const doubled = numbers.map(num => num * 2);
console.log(doubled); // [2, 4, 6](新数组)
特点:
- 回调函数必须
return
结果 - 不修改原数组
- 适合转换数据格式(如从对象数组中提取特定字段)
2. filter()
- 筛选元素
用途:返回符合条件的所有元素组成的新数组(子集)。
语法:
const newArray = array.filter((element, index, array) => { ... });
示例:
const numbers = [1, 2, 3, 4, 5];
const evens = numbers.filter(num => num % 2 === 0);
console.log(evens); // [2, 4](新数组)
特点:
- 回调函数返回布尔值(
true
保留元素) - 新数组长度 ≤ 原数组长度
- 适合数据过滤(如删除无效数据)
3. find()
- 查找单个元素
用途:返回第一个符合条件的元素,找不到时返回 undefined
。
语法:
const element = array.find((element, index, array) => { ... });
示例:
const users = [
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" }
];
const user = users.find(u => u.id === 2);
console.log(user); // {id: 2, name: "Bob"}(单个元素)
特点:
- 找到第一个匹配项后立即停止遍历
- 适合搜索唯一值(如按ID查找用户)
- 比
filter()[0]
性能更高
4. forEach()
- 遍历操作(无返回值)
用途:遍历数组执行操作(如修改元素、打印等),无返回值。
语法:
array.forEach((element, index, array) => { ... });
示例:
const letters = ["a", "b", "c"];
letters.forEach(letter => console.log(letter));
// 输出: "a" "b" "c"(无返回值)
特点:
- 回调函数不需
return
- 适合执行副作用操作(修改外部变量、DOM操作等)
- 不能使用
break
中断(用for...of
替代)
⚠️ 关键区别总结
-
返回值不同:
map()
/filter()
返回新数组find()
返回元素forEach()
返回undefined
-
用途差异:
- 需要转换数据 →
map()
- 需要数据子集 →
filter()
- 需要查找单条数据 →
find()
- 只需遍历操作 →
forEach()
- 需要转换数据 →
-
性能注意:
find()
在匹配后停止遍历,适合大型数组优化- 避免在
forEach
中修改数组长度(可能导致意外行为)
链式调用示例
// 从用户列表中筛选活跃用户并提取用户名
const activeUserNames = users
.filter(user => user.isActive) // 先过滤
.map(user => user.name); // 再映射
// 等价于 forEach 的链式操作(不推荐)
let names = [];
users.forEach(user => {
if (user.isActive) names.push(user.name);
});
📌 最佳实践:优先使用
map()
/filter()
等纯函数操作,避免在forEach
中修改数据以保持代码可预测性。