map用于一对一转换并返回等长新数组,filter用于条件筛选并返回真值元素组成的新数组;二者均不修改原数组,常组合使用(先filter后map)以提升可读性与性能。

map 和 filter 是什么,它们最常用来做什么
map 和 filter 都是 JavaScript 数组的原生方法,用于对数组元素做**不可变操作**:不修改原数组,而是返回一个新数组。map 适合「一对一转换」,比如把每个数字翻倍、把对象数组提取某个字段;filter 适合「条件筛选」,比如只保留大于 10 的数、只留下状态为 'active' 的用户。
map 的基本用法和容易踩的坑
map 接收一个回调函数,该函数会被调用 每次遍历一个元素时,并把返回值收集进新数组。它总是返回与原数组等长的新数组 —— 即使回调里写 return undefined 或没写 return,也会塞进 undefined。
- 回调函数默认接收三个参数:
item、index、array,但通常只用第一个 - 不能跳过某项(不像
filter),想“跳过”得显式返回undefined或null,但那仍占一个位置 - 如果需要改变长度,别硬套
map,该用filter就用filter,该用flatMap就用flatMap
const nums = [1, 2, 3]; const doubled = nums.map(n => n * 2); // [2, 4, 6]const users = [{id: 1, name: 'Alice'}, {id: 2, name: 'Bob'}]; const names = users.map(u => u.name); // ['Alice', 'Bob']
filter 的行为细节和常见误用
filter 同样接收一个回调函数,但它只把回调返回「真值」(truthy)的元素放进新数组。注意:返回 0、''、false、null、undefined、NaN 都算假值,对应元素会被过滤掉。
- 回调函数也接收
item、index、array三个参数 - 不要在
filter回调里做副作用(比如发请求、改全局变量),它本意是纯函数式筛选 - 想同时转换+筛选?别链式调用
map().filter()(性能差),优先考虑flatMap或一次循环手动构建
const scores = [85, 92, 76, 100, 54]; const passing = scores.filter(s => s >= 60); // [85, 92, 76, 100]const items = [{done: true}, {done: false}, {done: true}]; const doneItems = items.filter(i => i.done); // [{done: true}, {done: true}]
map 和 filter 组合使用的典型场景
实际开发中,常先 filter 再 map:比如从用户列表中筛出管理员,再提取他们的邮箱。这种组合清晰、可读性强,且符合数据流直觉。
立即学习“Java免费学习笔记(深入)”;
- 顺序很重要:先
filter再map能减少后续处理的数据量 - 避免在
map中嵌套条件逻辑来模拟filter,那样会让语义模糊、难以测试 - ESLint 会警告
map中出现if+return undefined的模式,就是因为它违背了map的设计意图
const users = [
{role: 'admin', email: 'a@ex.com'},
{role: 'user', email: 'b@ex.com'},
{role: 'admin', email: 'c@ex.com'}
];
const adminEmails = users
.filter(u => u.role === 'admin')
.map(u => u.email); // ['a@ex.com', 'c@ex.com']
真正难的不是记住语法,而是判断什么时候该用 map、什么时候该用 filter、什么时候两者都不够用——比如要扁平化嵌套数组、要按条件分组、要提前终止遍历,就得换别的方法或手写循环。











