一文搞懂reduce的用法和使用场景!

简介: 前言JavaScript 中的数组操作方法有好几十种,有的很简单,有的稍显复杂。而今天我们单独拿出来讲的便是 reduce 方法,为什么单独把 reduce 拿出来说呢?因为它算是 JS 数组方法里面较为复杂的一个了,而且很多面试官非常喜欢让面试者手动实现 reduce,所以我们有必要好好学一学这个数组方法,本篇文章主要是以学习 reduce 为主,后续会推出手写 reduce 的文章。

1.基本概念


想要学习一个 API 或者新的知识,我们通常是先去看看官网,有了大概的了解,我们才能深入下去学习,学习 reduce 一样,我们同样先去看看官网对它的解释。


官方解释:


reduce() 方法对数组中的每个元素按序执行一个由您提供的 reducer 函数,每一次运行 reducer 会将先前元素的计算结果作为参数传入,最后将其结果汇总为单个返回值。


第一次执行回调函数时,不存在“上一次的计算结果”。如果需要回调函数从数组索引为 0 的元素开始执行,则需要传递初始值。否则,数组索引为 0 的元素将被作为初始值 initialValue,迭代器将从第二个元素开始执行(索引为 1 而不是 0)。


从上面我们可以看出,官网的解释也蛮多的,说明这个 API 不是那么的简单。大家可能正对于第一段话还比较好理解,无非就是 reduce 方法接收一个回调函数,每一次回调函数的计算结果将被当作下一个回调函数的执行参数,这一点就很类似于我们熟知的 map 等方法了。


第二段话大家可能就没有那么容易理解了,我们可以拿 map 来举例,我们都知道 map 循环数组的方式如下:


arr.map((item) => {})


map 接收一个回调函数,回调函数的参数就是每一个数组元素,我们这里的 reduce 方法也是接收的一个回调函数,但是回调函数的参数不再是数组元素了,而是上一次执行回调函数的执行结果或者说是即使算结果。这里我们就有疑问,第一次执行回调函数是没有


上一次的执行结果的,那么它的参数是多少呢?这就是官方第二段内容解释的:第一次执行回调函数,参数应该是初始值,初始值我们可以设置,如果我们没有设置,那么初始值就是数组第一个元素。


语法:


上面一大段话大家看起来可能比较头痛,我们还是来看代码吧,更好理解。


reduce((previousValue, currentValue, currentIndex, array) => {}, initialValue)
// 简洁语法
reduce(callbackFn, initialValue)


reduce 的语法非常好理解,reduce 方法接收两个参数:回调函数和初始值。这里所说得到初始值就是前面我们说的回调函数第一次执行时的参数。


参数详解:


  • callbackFn:回调函数
  • previousValue:上一次回调函数的返回值,第一次调用回调函数时,如果指定的初始值 initialValue,那么该参数值就是 initialValue,否则就是数组元素的第一个。
  • currentValue:数组中正在处理的元素。在第一次调用时,若指定了初始值 initialValue,那么当前处理的元素就是数组的第一个元素,否则的话就是第二个元素。
  • currentIndex:数组中正在处理的元素的索引。若指定了初始值 initialValue,则起始索引号为 0,否则从索引 1 起始。
  • array:用于遍历的数组。
  • initialValue:初始值,也就是第一次调用回调函数时参数 previousValue


是否指定初始值将会影响其它几个参数的值。


从参数详解可以看出,initialValue 初始值很重要,因为它是否出现极大的影响了其它参数的值。


返回值:

reduce 方法的返回值就是遍历所有数组执行回调函数后的返回值。


2.基本使用


reduce 的基本语法和概念我们了解了,那么我们一起来看看它最重要的使用方式。这里我们需要分为两种情况,一种是有初始值 initialValue,一种是没有初始值 initialValue,因为它们两种的情况还是蛮大的。


2.1 有 initialValue


回顾一下:有初始值 initialValue,则回调函数第一次执行时的 previousValue 为初始值,currentValue 为数组元素的第一个,currentIndex0


代码如下:


let arr = [1, 2, 3, 4, 5, 6, 7, 8];
const total = arr.reduce((previousValue, currentValue) => {
  return previousValue + currentValue; // 100 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8
}, 100);
console.log(total); // 136


上段代码中我们使用 reduce 方法循环了数组 arr,并且设置了初始值 100,第一次执行回调函数时,previousValue100currentValue1,返回结果为 101101 作为第二次循环的 previousValue 传入回调函数,返回 101+2=103,依次类推......。


上段代码中我们少些了两个参数:currentIndex,和 array。我们把这两个参数带上再来看看什么结果。


代码如下:


let arr = [1, 2, 3, 4, 5, 6, 7, 8];
const total = arr.reduce((previousValue, currentValue, currentIndex, array) => {
  console.log(previousValue, currentValue, currentIndex, array)
  return previousValue + currentValue; // 100 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8
}, 100);
console.log(total); // 136


输出结果:



59.png

59.png

2.2 没有 initialValue


接下来我们再来尝试下没有初始值 initialValue 时,执行结果是什么?我们采用同样的代码,这样更好分析结果。


代码如下:


let arr = [1, 2, 3, 4, 5, 6, 7, 8];
const total = arr.reduce((previousValue, currentValue, currentIndex, array) => {
  console.log(previousValue, currentValue, currentIndex, array)
  return previousValue + currentValue; // 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8
});
console.log(total); // 36


输出结果:


58.png

从上面的执行结果可以看出,没有初始值时,第一次执行回调函数时 previousValue1,即数组的第一个元素,currentValue2,即数组第二个元素,currentIndex1。所以依次执行回调函数,实际上就是在累加数组中的元素。


3.使用场景


reduce 的使用场景是非常宽泛的,因为它很强大。当然,很多小伙伴可能会有这样一个疑问:使用 for 循环或者 forEach 循环能完成的功能,为什么要使用 reduce 呢?事实确实如此,有很多场景都有多种解决方案,我们选用我们最为熟悉、最为简单或者性能最好的方式就行了。

3.1 数组求和


在我们的基本使用中,其实就体现了数组求和的场景,这里我们简单温习一遍。


代码如下:

let arr1 = [1, 2, 3, 4, 5, 6, 7, 8];
const total1 = arr1.reduce((previousValue, currentValue) => {
  return previousValue + currentValue;
}, 0);
console.log(total1); // 36



3.2 数组对象求和


这和数组求和非常的类似,只不过我们的数组结稍微变得复杂了一点。


代码如下:

let arr2 = [{ x: 1 }, { x: 2 }, { x: 3 }];
const total2 = arr2.reduce((previousValue, currentValue) => {
  return previousValue + currentValue.x;
}, 0);
console.log(total2); // 6


举这个例子的目的就是让大家重点理解 previousValuecurrentValue 的关系。


3.3 二维数组转为一维数组


这种场景也可以称作为数组的扁平化,只不过这儿只针对于二维数组的扁平化。


代码如下:

let arr3 = [[0, 1], [2, 3], [4, 5]];
const flattened = arr3.reduce((previousValue, currentValue) => {
  return previousValue.concat(currentValue);
}, [])
console.log(flattened); // [0, 1, 2, 3, 4, 5]


代码中我们将初始值设置为了[],然后利用 concat 将数组中的每一项与初始值拼接,得到一个新的数组。


3.4 计算数组元素出现次数


这种场景通常出现在算法题当中,借助 reduce 我们简单实现它。


代码如下:

let names = ['小猪课堂', '张三', '李四', '王五', '小猪课堂']
let countedNames = names.reduce(function (allNames, name) {
  // 判断当前数组元素是否出现过
  if (name in allNames) {
    allNames[name]++
  } else {
    allNames[name] = 1
  }
  return allNames
}, {})
console.log(countedNames); // {小猪课堂: 2, 张三: 1, 李四: 1, 王五: 1}


上段代码中我们主要学习的是实现思路,我们通过键值对的形式巧妙的将出现的次数存储下来。


总结


reduce 的使用场景远不止上面几种,我们这里只是举例了一些简单场景,实际上 reduce 还可以在很多复杂的场景下使用,这都得益于它的初始值概念,以及回调函数 previousValue 得概念。至于更多使用场景,还需要大家自行探索自行总结了。


如果觉得文章太繁琐或者没看懂,可以观看视频: 小猪课堂



相关文章
ECharts 提示框组件Tooltip属性大全(包含文本注释)
ECharts 提示框组件Tooltip属性大全(包含文本注释)
1963 0
|
6月前
|
JavaScript 前端开发
js小数运算出现的问题(精度丢失)及解决办法-亲测有效
JavaScript浮点数运算存在精度丢失问题,如0.1+0.2不等于0.3。原因是十进制小数转二进制时可能出现无限循环,导致舍入误差。本文提供一种精度处理方法,通过将小数转为整数运算后再还原,实现加减乘除的精确计算,解决常见浮点运算误差问题。
1071 0
|
JavaScript API 索引
js中的reduce()方法 讲解 和实现
`reduce()` 方法对数组元素依次应用一个回调函数,将结果累计并最终返回单一值。语法为 `reduce(callback(accumulator, currentValue, currentIndex, array), initialValue)`。参数包括累计器(初次为初始值或首元素)、当前元素值、索引及数组自身。此方法需返回值供下一轮迭代使用。常见应用场景包括计算数组总和与平均值、统计元素频率、过滤与转换数组内容及去除重复项等。例如,可通过 `reduce()` 快速计算 `[1, 2, 3, 4, 5]` 的总和或对对象属性值求和。此外,还可自定义实现 `reduce()` 方法
7137 1
|
前端开发 数据处理
对象数据的读取,看这一篇就够了!Object.keys()、Object.values()和Object.entries()用法详解;如何获取对象原型链上的属性
Object.keys()、Object.values()和Object.entries()都是利于对象操作的便捷方法,能有效提升数据处理的效率。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
Web App开发 缓存 JavaScript
如何检测和解决闭包引起的内存泄露
闭包引起的内存泄露是JavaScript开发中常见的问题。本文介绍了闭包导致内存泄露的原因,以及如何通过工具检测和代码优化来解决这些问题。
echarts如何设置滚动条(dataZoom),实现横向或纵向滚动
echarts如何设置滚动条(dataZoom),实现横向或纵向滚动
echarts如何设置滚动条(dataZoom),实现横向或纵向滚动
|
JSON JavaScript 前端开发
vue中使用echarts实现省市地图绘制,根据数据在地图上显示柱状图信息,增加涟漪特效动画效果
vue中使用echarts实现省市地图绘制,根据数据在地图上显示柱状图信息,增加涟漪特效动画效果
4695 0
|
JavaScript
在Vue项目中vue-quill-editor的安装与使用【详细图解+过程+包含图片的缩放拖拽】
文章详细介绍了在Vue项目中安装和使用`vue-quill-editor`的步骤,包括如何通过npm安装、局部挂载、在Vue页面中引入和配置使用。同时,还提供了如何实现图片的缩放和拖拽功能的进阶教程,涉及到安装额外的插件`quill-image-drop-module`和`quill-image-resize-module`,以及对Webpack配置的调整。最后,文章还提供了实际效果展示和一些后续可能的拓展功能,如上传视频和将图片上传到服务器等。
在Vue项目中vue-quill-editor的安装与使用【详细图解+过程+包含图片的缩放拖拽】
|
JavaScript 前端开发
js数组排序的方法
js数组排序的方法
416 1

热门文章

最新文章