forEach(),map(),filter()和reduce(),find()区别

本文深入解析了JavaScript中数组的forEach(), map(), filter(), reduce() 和 find() 方法的区别与应用场景,通过生动的比喻帮助理解每个方法的特点,以及它们如何在不改变原数组的情况下,进行遍历、映射、过滤、累加和查找操作。

forEach(),map(),filter()和reduce(),find()区别

这几种都是数组的遍历方法方法用法上容易混淆,这里写下我的理解

forEach()

支持:除去(ie678)

forEach只是简单的将数组遍历,类似于军人接受检阅,但是检阅结束并不会返回任何东西,也不会改变原数组,forEach的返回永远是undefind

    let total = null
    let arr = [1,2,3]
    let result = arr.forEach(a => {
        total += a
        return a + 1
    })
    console.log(result) //undefind
    console.log(total) //6
    console.log(arr) //[1,2,3]
forEach与for..in在数组的处理方式上是一致的,区别在于for…in可以遍历对象上的所有可枚举属性,forEach只是数组上的一个函数

map()

支持:除去(ie678)

map可以比喻成去超市买东西,你拿了一个物品清单,然后服务员帮你拿好东西,返回给你一个物品的新数组,但是对清单原数组不发生改变

let goodsList = ['apple','pear','orange']
let goods = goodList.map(good => {
  return superMarket.getGoods(good)
})
 console.log(goodsList) //['apple','pear','orange']
 console.log(goods) //三个物品对象

reduce()

支持:除去(ie678)

reduce主要是为了对所有数组进行累加,最后返回一个值,不改变原数组,类似让男生把排队把把身高加起来

let totalHight = boys.reduce((counetedHight/*当前的高度总和*/,boy/*数组当前遍历到的元素*/)=> {
  return countedHigh + boy.hight
})

filter()

支持:除去(ie678)

filter()就是让男生排队身高高于180的就归入到新数组中,最后返回一个里面装着所有180+的男生的数组,不改变原数组

let highBoys = boys.filter((boy/数组当前遍历到的元素/)=> {
  return boy.highy >= 180
}
 console.log(highBoys) // [boy,boy,....]

find()

支持:ie各版本都不支持

find()函数就是你去找人想找一个180的男生帮你去搬砖,只要找到第一个就停止遍历,因为只要找一个,为了减少无用的操作,虽然其他方法也能实现同样的要过,但是最好用find()

let highBoy = boys.filter((boy/数组当前遍历到的元素/)=> {
  return boy.highy >= 180
}
 console.log(highBoy) // boy

总结

数组以上的方法都不会该改变原数组,但是都不兼容ie的低版本,所以如果有兼容需求就避免使用,或者用babal-polyfill编译成替代写法
--------------------- 
作者:何其涛 
来源:优快云 
原文:https://blog.youkuaiyun.com/deng1456694385/article/details/80295988 
版权声明:本文为博主原创文章,转载请附上博文链接!

<think>我们被要求比较JavaScript中的mapfilterforEach数组方法的相同点区别。 根据引用[1][2][3][4],我们可以总结如下: 相同点: 1. 都是数组的迭代方法,用于遍历数组。 2. 都不会改变原数组(除非在回调函数中直接修改原数组,但这并不是这些方法的直接行为,而是回调函数的副作用)。 3. 都接受一个回调函数作为参数,该回调函数可以接收三个参数:当前元素、当前索引原数组。 区别: 1. 返回值: - map():返回一个新数组,新数组的元素是原数组元素经过回调函数处理后的结果。 - filter():返回一个新数组,新数组包含原数组中满足回调函数条件的元素(即回调函数返回true的元素)。 - forEach():没有返回值(即返回undefined),仅仅是对每个元素执行回调函数。 2. 用途: - map():用于对数组的每个元素进行转换或映射,生成一个与原数组长度相同的新数组。 - filter():用于筛选数组中的元素,生成一个由满足条件的元素组成的新数组(长度可能小于原数组)。 - forEach():用于遍历数组,执行一些操作(如打印、修改外部变量等),不生成新数组。 3. 执行行为: - map()filter()都会遍历数组的每一个元素(除非在遍历过程中数组被修改导致长度变化)。 - forEach()同样会遍历每一个元素,但无法中断(除非抛出异常)。 - 注意:与some()find()不同,这三个方法都会遍历所有元素(除非在遍历过程中被中断,但通常不会)。 4. 链式调用: - 由于map()filter()返回数组,因此它们可以链式调用(如map().filter())。 - forEach()返回undefined,因此不能链式调用(除非在回调函数中操作原数组,但一般不推荐)。 5. 是否改变原数组: - 这三个方法本身不会改变原数组(注意:回调函数中如果修改了原数组,则原数组可能会被改变,但这属于副作用,不是方法本身的行为)。 根据引用[3]的表格,我们可以清晰地看到: | 方法 | 返回值 | 用途 | 是否改变原数组 | 执行次数 | |----------|---------------------|------------------------------|----------------|----------------| | map() | 新数组(同长度) | 对每个元素加工后返回新数组 | 否 | 遍历所有元素 | | filter() | 新数组(子集) | 筛选符合条件的元素组成新数组 | 否 | 遍历所有元素 | | forEach()| undefined | 遍历数组(用于副作用操作) | 否 | 遍历所有元素 | 另外,引用[1]中提到了mapfilter结合使用的例子,展示了链式调用的便利性。 示例代码: 1. map() 示例: ```javascript const numbers = [1, 2, 3, 4]; const doubled = numbers.map(num => num * 2); console.log(doubled); // 输出: [2, 4, 6, 8] ``` 2. filter() 示例: ```javascript const numbers = [1, 2, 3, 4]; const evens = numbers.filter(num => num % 2 === 0); console.log(evens); // 输出: [2, 4] ``` 3. forEach() 示例: ```javascript const numbers = [1, 2, 3, 4]; numbers.forEach(num => console.log(num)); // 输出: 1, 2, 3, 4(每行一个) ``` 4. map()filter()链式调用示例(引用[1]): ```javascript const numbers = [1, 2, 3, 4]; const result = numbers.map(num => num * 2).filter(num => num % 2 === 0); console.log(result); // 输出: [2, 4, 6, 8] (注意:这里所有元素都是偶数,所以全部保留) ``` 注意:在链式调用中,先执行map()将每个元素乘以2,然后filter()过滤出偶数。由于乘以2后都是偶数,所以全部保留。 总结: - 当需要根据原数组创建一个新数组(元素是原数组元素的变换)时,使用map()。 - 当需要从原数组中筛选出符合条件的元素组成新数组时,使用filter()。 - 当只需要遍历数组并执行一些操作(如打印、更新外部状态等),而不需要新数组时,使用forEach()。 另外,注意性能:在大型数组上,链式调用mapfilter会创建中间数组,如果考虑性能,可以使用reduce()或者循环来避免中间数组,但通常链式调用更清晰。 相关问题: 1. 如何优化JavaScript数组链式操作的性能? 2. 除了mapfilterforEach,JavaScript还有哪些常用的数组迭代方法? 3. 在什么情况下应该使用reduce()代替map()filter()的组合?</think>### JavaScript数组方法:`map()`、`filter()`、`forEach()` 的相同点与区别 #### 一、相同点 1. **迭代功能** 三者都用于遍历数组元素,对每个元素执行指定操作[^2][^3]。 2. **回调函数参数** 均接受一个回调函数,参数格式相同: ```javascript (currentElement, index, originalArray) => { ... } ``` 3. **不修改原数组** 都是纯函数,**不会改变原数组**(除非在回调中显式修改)[^3]。 4. **支持链式调用** 可与其他数组方法组合使用(如 `map().filter()`)[^1]。 --- #### 二、核心区别 | 方法 | 返回值 | 用途 | 执行特点 | 是否创建新数组 | |------------|----------------|------------------------------|------------------------|----------------| | **`map()`** | 新数组 | 元素转换/映射 | 处理所有元素 | ✅ 是 | | **`filter()`** | 新数组(子集) | 条件筛选 | 处理所有元素 | ✅ 是 | | **`forEach()`** | `undefined` | 遍历操作(副作用) | 处理所有元素 | ❌ 否 | --- #### 三、详细解析与示例 1. **`map()` - 映射转换** 返回与原数组**长度相同**的新数组,元素是回调函数的返回值[^3]。 ```javascript const nums = [1, 2, 3]; const doubled = nums.map(n => n * 2); console.log(doubled); // [2, 4, 6] (新数组) ``` 2. **`filter()` - 条件筛选** 返回**满足条件**的元素组成的新数组(长度 ≤ 原数组)[^3][^4]。 ```javascript const nums = [1, 2, 3, 4]; const evens = nums.filter(n => n % 2 === 0); console.log(evens); // [2, 4] (新数组) ``` 3. **`forEach()` - 遍历操作** 无返回值,仅用于遍历(如打印、修改外部变量)[^2][^3]。 ```javascript const nums = [1, 2, 3]; let sum = 0; nums.forEach(n => sum += n); console.log(sum); // 6 (外部变量改变) ``` --- #### 四、组合使用示例 `map()` + `filter()` 实现复杂操作[^1]: ```javascript const nums = [1, 2, 3, 4]; const result = nums .map(n => n * 3) // [3, 6, 9, 12] .filter(n => n > 5); // [6, 9, 12] console.log(result); ``` --- #### 五、使用场景总结 | 方法 | 典型场景 | |-------------|------------------------------------------| | **`map()`** | 数据格式转换(如 API 响应处理) | | **`filter()`** | 数据筛选(如过滤无效值、分类) | | **`forEach()`** | 执行副作用(如 DOM 操作、日志记录) | > 💡 **关键区别**: > - 需要**新数组** → 选 `map()` 或 `filter()` > - 只需**遍历操作** → 选 `forEach()` > - 需**链式处理** → 优先 `map()`/`filter()` --- ### 相关问题 1. 如何用 `reduce()` 替代 `map()` `filter()` 的组合? 2. `forEach()` 中修改元素会影响原数组吗? 3. ES6 新增的 `flatMap()` 与 `map()` 有何区别
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值