JavaScript 数组方法:forEach、map、filter 的使用
处理数组是编程中最常见的任务之一。JavaScript 提供了多种内置方法来高效操作数组,其中 forEach、map 和 filter 是最基础也最常用的三个。它们能让你用更少的代码完成遍历、转换和筛选操作,避免手动写 for 循环带来的繁琐和错误。
forEach:对每个元素执行操作
使用 forEach 对数组中的每个元素执行指定操作,但不返回新数组。它适用于你想“做点什么”,比如打印日志、更新 DOM 或调用 API,但不需要改变原数组结构。
-
定义一个数组,例如:
const numbers = [1, 2, 3, 4]; -
调用
forEach方法,传入一个函数作为参数。该函数会自动接收当前元素、索引和原数组(后两者可选):numbers.forEach((item, index) => { console.log(`第 ${index} 项是: ${item}`); });执行后控制台将输出:
第 0 项是: 1 第 1 项是: 2 第 2 项是: 3 第 3 项是: 4 -
注意:
forEach的回调函数不能使用return提前终止循环。如果需要中途退出,应改用普通for循环。
map:创建一个新数组
使用 map 将原数组的每个元素“映射”为新值,并返回一个全新数组。原数组不会被修改,这是函数式编程的核心思想。
-
准备一个源数组,例如用户年龄列表:
const ages = [18, 25, 32, 40]; -
调用
map方法,在回调函数中返回你想要的新值:const canVote = ages.map(age => age >= 18);结果
canVote是[true, true, true, true]。 -
常见用途包括数据格式转换。例如,将用户对象数组转为姓名字符串数组:
const users = [ { name: 'Alice', id: 1 }, { name: 'Bob', id: 2 } ]; const names = users.map(user => user.name); // names 为 ['Alice', 'Bob'] -
关键点:
map的回调函数必须有返回值,否则新数组会全是undefined。
filter:筛选符合条件的元素
使用 filter 创建一个只包含满足条件元素的新数组。原数组保持不变。
-
定义一个待筛选的数组,比如商品列表:
const products = [ { name: '手机', price: 3000 }, { name: '耳机', price: 200 }, { name: '电脑', price: 8000 } ]; -
调用
filter方法,在回调函数中返回一个布尔值(true表示保留该元素):const expensive = products.filter(product => product.price > 1000);结果
expensive包含手机和电脑两项。 -
可以组合多个条件。例如筛选价格在 200 到 5000 之间的商品:
const midRange = products.filter(p => p.price >= 200 && p.price <= 5000); -
注意:
filter不会跳过空位(即稀疏数组中的“洞”),但会跳过值为undefined或null的元素(除非你的条件明确包含它们)。
三者对比与选择
选择哪个方法取决于你的目标:是执行副作用、转换数据,还是筛选数据?
| 方法 | 是否返回新数组 | 是否修改原数组 | 回调函数是否需返回值 | 典型用途 |
|---|---|---|---|---|
forEach |
否 | 否 | 否 | 打印、发送请求、更新状态等 |
map |
是 | 否 | 是 | 数据转换、格式化、计算新值 |
filter |
是 | 否 | 是 | 按条件保留部分元素 |
组合使用:链式调用
这三个方法可以链式调用,实现复杂的数据处理流程。
-
从一组数字中选出偶数,然后平方:
const nums = [1, 2, 3, 4, 5, 6]; const result = nums .filter(n => n % 2 === 0) // [2, 4, 6] .map(n => n * n); // [4, 16, 36] -
处理用户数据:过滤成年用户,提取姓名并转为大写:
const people = [ { name: 'alice', age: 17 }, { name: 'bob', age: 20 }, { name: 'charlie', age: 16 } ]; const adultNames = people .filter(p => p.age >= 18) .map(p => p.name.toUpperCase()); // 结果: ['BOB'] -
性能提示:链式调用会创建中间数组。如果数组极大且性能敏感,可考虑合并逻辑到单次遍历中。但对于绝大多数场景,链式写法清晰易读,优先推荐。
常见错误与注意事项
-
不要在
map或filter中执行副作用(如修改外部变量或调用console.log)。这会让代码难以理解和测试。副作用应放在forEach中。 -
避免在
forEach中使用异步操作而不处理并发。例如:// 错误:无法保证顺序,且无法 await urls.forEach(url => fetch(url));正确做法是使用
for...of或Promise.all配合map:const promises = urls.map(url => fetch(url)); const results = await Promise.all(promises); -
map和filter总是返回新数组,即使内容未变。不要用它们来检查是否存在某个元素——此时应使用some或find。 -
箭头函数简化写法:当回调函数只有一行返回语句时,可省略花括号和
return:// 等价写法 arr.map(x => x * 2); arr.map(x => { return x * 2; });

暂无评论,快来抢沙发吧!