JavaScript数组方法reduce详解

news2025/2/23 15:37:26

JavaScript数组方法reduce详解

在这里插入图片描述

目录

  • JavaScript数组方法reduce详解
    • 一,前言
    • 二,核心语法
    • 三,案例
      • 1.求和
      • 2.找最大值
      • 3.数组转对象
      • 4.复合操作(同时实现 map + filter)
    • 四,常见错误
      • 1.空数组没有初始值
      • 2.没有返回累加值
      • 3.reduce 方法在遍历数组时,依赖于数组的长度和内容,如果在遍历过程中修改了数组(例如删除元素),会导致遍历逻辑混乱,结果不可预测。
    • 五,reduce 的 polyfill
    • 六,总结

一,前言

Reduce 是一种在函数式编程中常见的操作,它可以将一个序列(比如列表,数组)的所有元素通过某种规约逻辑合并成一个单一的数值。Reduce 的概念最早起源于函数式编程语言 Lisp,后来被广泛应用于其他语言中,如 Python ,javaScript。本文会用最易懂的方式帮你彻底掌握JavaScript数组reduce()方法。我们先从基础开始,逐步深入,最后通过实际案例巩固知识,最重要的是希望能够带给你一些思考。

二,核心语法

arr.reduce(callback(accumulator, currentValue, index, array), initialValue)
Accumulator(累计值)
CurrentValue(当前元素)
Index(当前索引)
Array(原数组)
initialValue(Accumulator的初始值)

三,案例

1.求和

const nums = [1, 2, 3];
const sum = nums.reduce((acc, num) => acc + num, 0);

代码分析:
此求和案例分别用了参数acc和num代表Accumulator和CurrentValue,并且将Accumulator的初始值赋为0。
运算步骤:
1,初始值为0,acc为0加第一次的当前值1 返回1
2,acc为1加第二次循环的当前值2,返回3
3,acc为3加第三次循环的当前值3,返回6

2.找最大值

const max = [4, 2, 7, 5].reduce((a, b) => Math.max(a, b), -Infinity);

代码分析:
此求最大值案例分别用了参数a和b代表Accumulator和CurrentValue,并且将Accumulator的初始值赋为-Infinity(负无穷大)。
运算步骤:
1,首先是负无穷和第一次的当前值4比较,返回4
2,a为4,和第二次的当前值2比较,返回4
3,a为4,和第三次当前值7比较,返回7
4,a为7,和第四次当前值5比较,返回7
说明:
-Infinity 是 JavaScript 中的一个特殊值,表示负无穷大。它不是变量,而是一个全局属性,属于 JavaScript 的 基本数据类型 之一。
这里也可以更换 -Infinity为100,那么max的返回值就是100。

3.数组转对象

const users = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' }
];

const userMap = users.reduce((obj, user) => {
  obj[user.id] = user;
  return obj; 
}, {});

返回结果:

{
    "1": {
        "id": 1,
        "name": "Alice"
    },
    "2": {
        "id": 2,
        "name": "Bob"
    }
}

说明:
数组转对象案例这里主要是想体现一下设置初始值的重要性
这里如果不设置其默认初始值可以先看一下返回结果的区别

const users = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' }
];

const userMap = users.reduce((obj, user) => {
  obj[user.id] = user;
  return obj; 
});

返回值:

{
    "2": {
        "id": 2,
        "name": "Bob"
    },
    "id": 1,
    "name": "Alice"
}

代码分析:
要想弄明白为什么没有设置空的初始值显示结果是这样,我们首先回到案例1求和的代码,
之前我们分析结论是基于有返回值的情况下得出的

1,初始值为0,acc为0加第一次的当前值1 返回1
2,acc为1加第二次循环的当前值2,返回3
3,acc为3加第三次循环的当前值3,返回6

那么如果对于求和案例不设置初始值又该如何分析呢?
对于没有设置初始值的reduce分析:第一次迭代时,acc 是数组的第一个元素,num 是数组的第二个元素。得到这个结论我们返回来分析代码:

const users = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' }
];

const userMap = users.reduce((obj, user) => {
  obj[user.id] = user;
  return obj; 
});

因为没有返回值,第一次obj是 { id: 1, name: ‘Alice’ },user是 { id: 2, name: ‘Bob’ }
执行 obj[user.id] = user 后,obj 变为 { id: 1, name: ‘Alice’, 2: { id: 2, name: ‘Bob’ } }。

注意:
JavaScript的reduce函数有没有设置初始值,直接影响第一次执行的Accumulator和CurrentValue

4.复合操作(同时实现 map + filter)

const numbers = [1, 2, 3, 4];
const doubledEvens = numbers.reduce((arr, num) => {
  if (num % 2 === 0) {
    arr.push(num * 2);
  }
  return arr;
}, []);
// 结果:[4, 8](先过滤偶数,再翻倍)

代码分析:
此求和案例分别用了参数arr和num代表Accumulator和CurrentValue,并且将Accumulator的初始值赋为[]。此例子中必须要设置Accumulator的初始值为[ ],否则,Accumulator的初始值是1,不是数组没有push方法就会报错。

四,常见错误

1.空数组没有初始值

[].reduce((a, b) => a + b); // 报错!

2.没有返回累加值

// 错误示例
[1,2,3].reduce((acc, num) => {
  acc + num; // 没有 return!
});
// 正确:必须显式返回 acc

3.reduce 方法在遍历数组时,依赖于数组的长度和内容,如果在遍历过程中修改了数组(例如删除元素),会导致遍历逻辑混乱,结果不可预测。

五,reduce 的 polyfill

Polyfill 是指在不支持某个新特性的旧浏览器中,用 JavaScript 实现该特性的代码。换句话说,它是一个“补丁”,用来填补浏览器原生功能的缺失。
用白话说就是自己实现reduce,通过自己实现 reduce,可以更深入地理解它的工作原理。

Array.prototype.myReduce = function (callback, initialValue) {
  // 1. 检查 this 是否为 null 或 undefined
  if (this == null) {
    throw new TypeError('Array.prototype.myReduce called on null or undefined');
  }

  // 2. 检查 callback 是否是函数
  if (typeof callback !== 'function') {
    throw new TypeError(callback + ' is not a function');
  }

  const array = Object(this); // 将 this 转换为对象
  const length = array.length >>> 0; // 确保 length 是正整数

  let accumulator;
  let startIndex = 0;

  // 3. 处理初始值
  if (arguments.length >= 2) {
    accumulator = initialValue; // 如果有初始值,直接使用
  } else {
    // 如果没有初始值,取数组的第一个元素作为初始值
    if (length === 0) {
      throw new TypeError('Reduce of empty array with no initial value');
    }
    accumulator = array[0];
    startIndex = 1; // 从第二个元素开始遍历
  }

  // 4. 遍历数组
  for (let i = startIndex; i < length; i++) {
    if (i in array) {
      // 调用回调函数,更新 accumulator
      accumulator = callback(accumulator, array[i], i, array);
    }
  }

  // 5. 返回最终结果
  return accumulator;
};

使用示例:

const nums = [1, 2, 3, 4];

// 求和
const sum = nums.myReduce((acc, num) => acc + num, 0);
console.log(sum); // 10

// 找最大值
const max = nums.myReduce((acc, num) => Math.max(acc, num), -Infinity);
console.log(max); // 4

// 数组转字符串
const str = nums.myReduce((acc, num) => acc + num.toString(), '');
console.log(str); // '1234'

六,总结

reduce的参数看起来多,但是认真体会上面的案例不难理解,难点是如何记住

Accumulator(累计值)
CurrentValue(当前元素)
Index(当前索引)
Array(原数组)

参数顺序口诀:“All Cows In Australia”(ACIA)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2303964.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机毕业设计SpringBoot+Vue.js服装商城 服装购物系统(源码+LW文档+PPT+讲解+开题报告)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

Web自动化中Selenium下Chrome与Edge的Webdriver常用Options参数

目录 引言 说明 Add_argument() 添加方式 常用参数 Add_experimental_option() 添加方式 常用方法 任务结束后仍然保持浏览器打开 禁用“Chrome 正受到自动测试软件的控制”提示 设置下载路径 禁用弹窗拦截 禁用图片加载 禁用 JavaScript 注意 引言 …

现代未来派品牌海报徽标设计无衬线英文字体安装包 THANKS LAB

THANK LAB 是一种高级未来主义的软字体&#xff0c;将时尚的现代设计与光滑圆润的边缘相结合&#xff0c;营造出大胆而平易近人的美感。这款字体非常适合品牌、海报、标题、UI/UX 和科幻主题项目&#xff0c;旨在激发创造力。THANK LAB Futuristic Soft Font 完全支持拉丁字母、…

【算法通关村 Day6】二叉树层次遍历

树与层次遍历青铜挑战 理解树的结构 通过中序和后序遍历序列恢复二叉树是一个经典的二叉树构建问题。给定二叉树的中序遍历序列和后序遍历序列&#xff0c;我们可以利用以下步骤进行恢复。 思路&#xff1a; 后序遍历的特点&#xff1a; 后序遍历的最后一个节点是树的根节点…

安全面试2

文章目录 简单描述一下什么是水平越权&#xff0c;什么是垂直越权&#xff0c;我要发现这两类漏洞&#xff0c;那我代码审计要注意什么地方水平越权&#xff1a;垂直越权&#xff1a;水平越权漏洞的审计重点垂直越权漏洞的审计重点 解释一下ssrf漏洞原理攻击场景修复方法 横向移…

【JavaScript进阶】构造函数数据常用函数

目录 本章节用到的所有素材都可以找到&#xff1a;素材自取~~~~ 1、深入对象 1.1创建对象三种方式 1.2 构造函数 练习 利用构造函数创建多个对象 实例化执行过程 1.3实例成员&静态成员 2. 内置构造函数 2.1 Object 2.2 Array 练习 员工涨薪计算成本 2.3 St…

在PiscTrace开发者版上直接处理图像色阶分布

在图像处理和计算机视觉中&#xff0c;色阶分布&#xff08;或称灰度分布&#xff09;是描述图像中像素强度分布的一个重要概念。它对于理解图像的亮度、对比度、纹理和细节等方面具有关键作用。通过色阶分布的分析&#xff0c;我们能够获得图像的整体信息&#xff0c;从而帮助…

趣味数学300题1981版-十五个正方形

分析&#xff1a;移动两根变成11个正方形很简单&#xff1a; 移动4根变成15个正方形&#xff0c;分析&#xff1a; 一个田字格包含5个正方形&#xff0c;若要15个正方形需要3个田字格&#xff0c;如果3个田字格完全不重合&#xff0c;需要6*318根火柴。如果合并正方形的边&…

Selenium实战案例1:论文pdf自动下载

在上一篇文章中&#xff0c;我们介绍了Selenium的基础用法和一些常见技巧。今天&#xff0c;我们将通过中国科学&#xff1a;信息科学网站内当前目录论文下载这一实战案例来进一步展示Selenium的web自动化流程。 目录 中国科学&#xff1a;信息科学当期目录论文下载 1.网页内…

nginx 反向代理 配置请求路由

nginx | 反向代理 | 配置请求路由 nginx简介 Nginx&#xff08;发音为“Engine-X”&#xff09;是一款高性能、开源的 Web 服务器和反向代理服务器&#xff0c;同时也支持邮件代理和负载均衡等功能。它由俄罗斯程序员伊戈尔西索夫&#xff08;Igor Sysoev&#xff09;于 2004…

用户中心项目教程(十)---注册里面的重定向排查和相关的修改

文章目录 1.注册逻辑的设计和实现2.解决自带的这个重定向的问题3.增加属性的相关操作4.关于如何修改页面上面的绿色按钮 1.注册逻辑的设计和实现 上次说到了的是登录功能&#xff0c;我们使用数据库里面存在的这个存在的账户和密码进行登录&#xff0c;但是是无法进行跳转的&a…

根据音频中的不同讲述人声音进行分离音频 | 基于ai的说话人声音分离项目

0.研究背景 在实际的开发中可能会遇到这样的问题&#xff0c;老板让你把音频中的每个讲话人的声音分离成不同的音频片段。你可以使用au等专业的音频处理软件手动分离。但是这样效率太慢了&#xff0c;现在ai这么发达&#xff0c;我们能否借助ai之力来分离一条音频中的不同的说…

【单片机】【UDS】 (单帧与多帧) 数据传输

对于使用 CAN 的诊断通信系统&#xff0c;每个单帧 (SF)、 第一帧 (FF)、 连续帧 (CF) 或流控 制帧 (FC) 有 8 字节数据场&#xff1b;其中单帧的 CAN_DL≤8 且第一帧的 FF_DL≤4095&#xff1b;下表 中已定义 每个报文的类型。 CAN FD 帧的数据场支持最大 64 个字节&#xff0…

WebXR教学 02 配置开发环境

默认操作系统为Windows 1.VS Code VS Code 是一款轻量级、功能强大的代码编辑器&#xff0c;适用于多种编程语言。 下载 步骤 1&#xff1a;访问 VS Code 官方网站 打开浏览器&#xff08;如 Chrome、Edge 等&#xff09;。 在地址栏输入以下网址&#xff1a; https://code.v…

MySql数据库运维学习笔记

数据库运维常识 DQL、DML、DCL 和 DDL 是 SQL&#xff08;结构化查询语言&#xff09;中的四个重要类别&#xff0c;它们分别用于不同类型的数据库操作&#xff0c;下面为你简单明了地解释这四类语句&#xff1a; 1. DQL&#xff08;数据查询语言&#xff0c;Data Query Langu…

宇树科技13家核心零部件供应商梳理!

2025年2月6日&#xff0c;摩根士丹利&#xff08;Morgan Stanley&#xff09;发布最新人形机器人研报&#xff1a;Humanoid 100: Mapping the Humanoid Robot Value Chain&#xff08;人形机器人100&#xff1a;全球人形机器人产业链梳理&#xff09;。 Humanoid 100清单清单中…

ARMS 助力假面科技研发运维提效,保障极致游戏体验

客户介绍与项目背景 假面科技成立于 2014 年&#xff0c;致力于打造创新的数字产品&#xff0c;火爆一时的“狼人杀”、“谁是卧底”、“足记相机”都是假面科技旗下产品&#xff0c;公司产品总数超过 40 款&#xff0c;覆盖用户数超过 2 亿人。 随着业务的持续发展&#xff…

趣味数学300题1981版-八个等式、五个5等于24

八个等式 分析&#xff1a;此问题的求解思路是按照最后一步运算的运算符号进行分类。示例中最后一步的运算是除法&#xff0c;只要被除数与除数相等且不为0&#xff0c;就可以得到结果1.因此我们还可以对于结果等于1的情况列出其他的算式。如果保持最后一步运算为除法运算&…

关闭超时订单和七天自动确认收货+RabbitMQ规范

关闭超时订单 创建订单之后的一段时间内未完成支付而关闭订单的操作&#xff0c;该功能一般要求每笔订单的超时时间是一致的 TTL&#xff08;Time To Live&#xff09;存活时间&#xff0c;只能被设置为某个固定的值&#xff0c;不能更改&#xff0c;否则抛出异常 死信&#…

【多模态处理篇一】【 深度解析DeepSeek图文匹配:CLIP模型迁移实战——从原理到落地的保姆级教程】

引言:当CLIP遇到DeepSeek,会发生什么化学反应? 如果说CLIP是OpenAI为多模态领域投下的"原子弹",那DeepSeek的迁移实战方案就是给这颗原子弹装上了精确制导系统。这个组合能让你用一张猫咪表情包搜到全网同类梗图,还能让电商平台自动生成百万级商品描述,甚至帮…