js中的reduce()方法 讲解 和实现

简介: `reduce()` 方法对数组元素依次应用一个回调函数,将结果累计并最终返回单一值。语法为 `reduce(callback(accumulator, currentValue, currentIndex, array), initialValue)`。参数包括累计器(初次为初始值或首元素)、当前元素值、索引及数组自身。此方法需返回值供下一轮迭代使用。常见应用场景包括计算数组总和与平均值、统计元素频率、过滤与转换数组内容及去除重复项等。例如,可通过 `reduce()` 快速计算 `[1, 2, 3, 4, 5]` 的总和或对对象属性值求和。此外,还可自定义实现 `reduce()` 方法

reduce()

① 介绍:

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

② 语法以及参数说明:

reduce(callback(accumulator, currentValue, currentIndex, array), initialValue)
  • accumulator : 上一次调用 callbackFn 的结果。在第一次调用时,如果指定了 initialValue 则为指定的值,否则为 array[0] 的值。
  • currentValue : 当前元素的值。在第一次调用时,如果指定了 initialValue,则为 array[0] 的值,否则为 array[1]

    • currentIndex : currentValue 在数组中的索引位置。在第一次调用时,如果指定了 initialValue 则为 0,否则为 1

    • array : 调用的数组本身

reduce使用的时候必须要有返回值,作为下次迭代的参数传入.后面实现源码的时候就会知道了,其实在for循环里面嵌套了一个callback函数

③ 使用场景

1. 求数组元素总和,求平均数

// 1. 求数组元素的和
const arr7 = [1, 2, 3, 4, 5]

// reduce要求有返回值的

const sum = arr7.reduce((temp,item,index,array)=>{
   
    console.log(temp,item); 
    return temp + item
},0)

const avg = sum / arr7.length
console.log(`平均值:${
     avg}`);

console.log("-------------------------");
console.log(`使用reduce api 求和之后:${
     sum}`);

// 下面看传统的求数组各个元素的总和的方法
let sum1 = 0;
arr7.forEach((item, index) => {
   
    sum1 += item
    console.log(index);
})
console.log(`使用forEach api 求和之后:${
     sum1}`);

accumulator(累加值) | currentValue(当前元素的值) | index(当前元素的索引) |
| ---------------- | -------------------- | -------------- |
| 0 | 1 | 0 |
| 1 | 2 | 1 |
| 3 | 3 | 2 |
| 6 | 4 | 3 |
| 10 | 5 | 4

2. 统计数组各个元素出现的个数

// 2. 统计数组里面重复字段出现的个数
const arr4 = ["上海", "北京", "广州", "济南", "北京"]
// 定义一个空数组,用来存储每个元素的出现次数
const countArr = arr4.reduce((temp, item) => {
   
    // 这个对象里面存在item :"上海","北京"... 等键,就将该键的值加一
    if (temp[item]) {
   
        temp[item]++
    } else {
    // 如果不存在,就将该键 加入到空对象中,并赋值表示出现一次
        temp[item] = 1
    }
    // 遍历完之后将这个对象进行返回
    return temp
}, {
   }) //{} 初始temp 为一个空对象
// 将countArr数组中的元素添加到temp数组中,并返回
console.log(countArr); // {上海:1,北京:2,广州:1,济南:1}

3. 数组过滤

这里可以使用reduce的第四个参数,initialValue初始值我们给他一个[] 空数组,作为累积值(上一次回调函数的返回值初始值),如果传入第四个参数 这里就是初始值.

如果数组中的某一项 能够整除2 就将该元素放入初始好的[]空数组,相反不能够整除2 我们就放入外面定义好的arr3这个数组里面.

当数组里面全部元素遍历完毕之后,我们再将temp进行一个return返回,这时候我们就拿到原数组里面所有能够整除2的元素了.

// 3. 对数组进行一个过滤 (奇偶数分离)
const numArr1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const arr3 = []
const filterNumArr = numArr1.reduce((temp, item) => {
   
    if (item % 2 === 0) {
   
        temp.push(item)
    } else {
   
        arr3.push(item)
    }
    return temp
}, [])
console.log(filterNumArr); // [2,4,6,8,10]
console.log(arr3);//[1,3,5,7,9]

4. 对数组各项进行相同的操作 (增加n倍,缩小n倍...)

这个和上面那个思路相同. 只不过执行的操作不同. 但都是通过内置的for循环对数组中的各个元素进行某个操作的.


// 4. 对数组各项进行相同的操作
const numArr = [1, 2, 3, 4, 5]
const doublenumArr = numArr.reduce((temp, item) => {
   
    temp.push(item * 2)
    return temp
}, [])
console.log(doublenumArr); // [2,4,6,8,10]

5. 数组去重

如果数组temp 不包含item也就是 arr5里面的各个元素,就将该元素放入temp.

这里使用到数组的另外一个api includes()

includes()方法是用于判断一个数组或字符串是否包含指定的值,并返回一个布尔值。该方法可以用于数组和字符串。


// 5. 数组去重
const arr5 = [2, 2, 3, 3, 5, 3, 5, 9, 9, 10]
const uniqueArr = arr5.reduce((temp, item) => {
   
    if (!temp.includes(item)) {
   
        temp.push(item)
    } else {
   
        console.log("重复的元素", item);
    }
    return temp

}, [])
console.log("数组去重",uniqueArr); // [2,3,5,9,10]

6. 对象属性值的总和

Object.values(cost) 返回该对象所有可枚举属性的值组成的数组


const cost = {
   
    "snack": 20,
    "cloth": 300,
    "drink": 50,
    "shop": 500
}

// 属性值的总和
// Object.values(cost) 转换为数组
const sum1 = Object.values(cost).reduce((temp, item) => {
   
    return temp + item
})
console.log(sum1); // 870

④ 实现一个reduce方法

// 自行封装一个reduce
Array.prototype.reduce1 = function (fn, initVal) {
   
    // 首先定义一个数组
    var arr = this;

    // 如果调用api的人第一个参数不是function,进行一个抛错
    if (typeof fn !== "function") {
   
        // 第一个参数必须是函数
        throw new TypeError("First argument must be a function");
    }

    // 第一种情况:使用者没有传入初始值initVal
    if (typeof initVal === "undefined") {
   
        // 初始值是数组的第一个元素
        initVal = arr[0];
        // 循环遍历数组
        for (var i = 1; i < arr.length; i++) {
   
            // 调用reduce方法
            //每次执行一遍这个fn函数 就会返回一个值 并且重新赋值给initvalue ,并在下次调用
            initVal = fn(initVal, arr[i], i, arr);

        }

    }
    // 第二种情况: 使用者传入了初始值 initVal
    else {
   
        for (var i = 0; i < arr.length; i++) {
   
            initVal = fn(initVal, arr[i], i, arr);
        }
    }

    // 最后将这个值进行一个返回
    return initVal

};

// 测试用例 求数组总和 
var arr = [1, 2, 3, 4, 5];
var sum = arr.reduce1((initVal, temp, index, arr) => {
   
    return initVal + temp;
});

console.log(sum); // 15

使用reduce() 可以搭配其他关于数组的api 实现更多的需求

目录
相关文章
|
15天前
|
JavaScript 前端开发 Java
js 垃圾回收机制的方法
JS回收机制方法讲解
|
2月前
|
前端开发 JavaScript
有没有方法可以保证在JavaScript中多个异步操作的执行顺序?
有没有方法可以保证在JavaScript中多个异步操作的执行顺序?
98 58
|
5月前
|
JavaScript 前端开发 程序员
前端原生Js批量修改页面元素属性的2个方法
原生 Js 的 getElementsByClassName 和 querySelectorAll 都能获取批量的页面元素,但是它们之间有些细微的差别,稍不注意,就很容易弄错!
110 1
|
1月前
|
JavaScript 前端开发 Java
深入理解 JavaScript 中的 Array.find() 方法:原理、性能优势与实用案例详解
Array.find() 是 JavaScript 数组方法中一个非常实用和强大的工具。它不仅提供了简洁的查找操作,还具有性能上的独特优势:返回的引用能够直接影响原数组的数据内容,使得数据更新更加高效。通过各种场景的展示,我们可以看到 Array.find() 在更新、条件查找和嵌套结构查找等场景中的广泛应用。 在实际开发中,掌握 Array.find() 的特性和使用技巧,可以让代码更加简洁高效,特别是在需要直接修改原数据内容的情形。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一
|
1月前
|
移动开发 运维 供应链
通过array.some()实现权限检查、表单验证、库存管理、内容审查和数据处理;js数组元素检查的方法,some()的使用详解,array.some与array.every的区别(附实际应用代码)
array.some()可以用来权限检查、表单验证、库存管理、内容审查和数据处理等数据校验工作,核心在于利用其短路机制,速度更快,节约性能。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
1月前
|
供应链 JavaScript 前端开发
通过array.every()实现数据验证、权限检查和一致性检查;js数组元素检查的方法,every()的使用详解,array.some与array.every的区别(附实际应用代码)
array.every()可以用来数据验证、权限检查、一致性检查等数据校验工作,核心在于利用其短路机制,速度更快,节约性能。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
5月前
|
监控 JavaScript Java
Node.js中内存泄漏的检测方法
检测内存泄漏需要综合运用多种方法,并结合实际的应用场景和代码特点进行分析。及时发现和解决内存泄漏问题,可以提高应用的稳定性和性能,避免潜在的风险和故障。同时,不断学习和掌握内存管理的知识,也是有效预防内存泄漏的重要途径。
414 62
|
3月前
|
JavaScript 前端开发 开发者
JavaScript字符串的常用方法
在JavaScript中,字符串处理是一个非常常见的任务。JavaScript提供了丰富的字符串操作方法,使开发者能够高效地处理和操作字符串。本文将详细介绍JavaScript字符串的常用方法,并提供示例代码以便更好地理解和应用这些方法。
79 13
|
5月前
|
缓存 JavaScript 前端开发
JavaScript 与 DOM 交互的基础及进阶技巧,涵盖 DOM 获取、修改、创建、删除元素的方法,事件处理,性能优化及与其他前端技术的结合,助你构建动态交互的网页应用
本文深入讲解了 JavaScript 与 DOM 交互的基础及进阶技巧,涵盖 DOM 获取、修改、创建、删除元素的方法,事件处理,性能优化及与其他前端技术的结合,助你构建动态交互的网页应用。
156 5
|
5月前
|
JavaScript 前端开发
js中的bind,call,apply方法的区别以及用法
JavaScript中,`bind`、`call`和`apply`均可改变函数的`this`指向并传递参数。其中,`bind`返回一个新函数,不立即执行;`call`和`apply`则立即执行,且`apply`的参数以数组形式传递。三者在改变`this`指向及传参上功能相似,但在执行时机和参数传递方式上有所区别。
74 1
下一篇
oss创建bucket