第一次见到reduce 是在js 的高级程序设计中,它的意思是把一个数组减少为一个数,举的例子是数组中元素的求和。它接受一个函数作为参数,函数又有两个参数,一个是prev, 前一个值,一个是next, 后一个值,然后函数体就是返回相加的值。

let array = [1, 3, 5];
let sum = array.reduce((prev, next) => {
return prev + next;
}) console.log(sum);
  我对reduce 的理解也仅限于此,只停留在了表面,当然,除了这个例子之后,我也不会用reduce. 今天在读js函数式编程相关书籍的时候,又遇到reduce, 仔细读了几遍,加深了理解,大体上懂了它的原理和用法。
  reduce 确实是把数组减少为一个值,也是接受一个函数作为参数,但它还有一个可选的第二个参数。对函数接受的两个参数的理解也有偏差,第一个参数准确来讲应该是个累计值,第二个参数应该是数组的每一个项的值。还是数组的求和为例,我们完全可以不用recude, 直接循环遍历数组就可以。那么我们该怎么做呢?
  先声明一个变量,来存储求和后的值。

let sum = 0;
  然后循环遍历数组的每一项,和sum 进行相加

for (let index = 0; index < array.length; index++) {
const element = array[index];
sum = sum + element;
}

  完全没有问题,可以求出数组中的元素的和。数组元素的求和应该都是这样的步骤,我们尝试把这个步骤封装一下, 先直接定义一个函数把所有步骤包含起来, 只把console.log(sum) 变成return sum;

function reduce () {

  let sum = 0;

  for (let index = 0; index < array.length; index++) {
const element = array[index];
sum = sum + element;
} return sum;
}

  现在来看封装的函数,可以发现有几个问题:

  1,let sum = 0 不太合适,在函数中固定一个变量的值,不具有灵活性。这个很简单,可以声明一个变量,让sum 等于传递进行的值。如果没有,可以默为0 , 变量为initValue;

  2,这个问题也很简单地,就是要遍历的数组,要把数组传递进来,所以要接受一个数组参数,用来进行遍历。
  3,这个问题可能不太好理解,但也是最关键的。第三个问题是在sum = sum + element;sum + element是这个函数要做的事情,如果不指定,这个reduce 函数只能做求和运算。我们想让这个函数更为通用,函数要做的事情就要让用户进行指定。要做的事情,在js 中,可以用函数进行表示,所以接受一个函数做为参数,这个函数要接受两个参数sum, elemnet, 然后在函数体中指定这个函数要做什么事情。由于sum + element 的值要赋值为sum, 所以这个函数还要有返回值。
function reduce (array, fn, initValue) {
let sum ; initValue ? (sum =initValue): (sum = 0); // 然后循环遍历数组的每一项,和sum 进行相加
for (let index = 0; index < array.length; index++) {
const element = array[index];
sum = fn(sum, element);
} return sum;
}

  调用我们自己封装的reduce 时行数组的求和

let result = reduce(array, (sum, element) => sum  + element);

  现在我们来对比原生的调用方式和自己封装的方式?可以发现没有本质不同。唯一的不同可能是我们的第一个参数是数组,而原生没有,这是因为原生的方法是定义在数组原型上,所 以没有接受数组作为参数,对于理解reduce 函数来说,这没有什么本质的不同。通过封装的过程,我们更能明白接受的函数的参数的意思。这个函数至少要接受两个参数,第一个参数的真正意义应该是调用函数所返回的值,由于在第一个调用函数之前,没有返回值,所以我们可以给它赋初值,或通过第三个参数,或直接调为0。 第二个参数,就是数组的每一项,只有不停的遍历数组中的每一项,最终才能把数组变成一个值。其实初值还有一个更好的办法,如果没有传递进来,可以取数组的第一项作为初始值。最终的函数可能如下:

const reduce = (array, fn, initialValue) => {
let sum;
if (initialValue) {
sum = initialValue;
for (const value of array) // 这里用了es6 在for of
sum = fn(sum, value)
}
else {
sum = array[0];
for (let i = 1; i < array.length; i++)
sum = fn(sum, array[i])
}
return sum;
}

  通过以上分析,我们可以看到,reduce函数真正的核心在于传递进去的函数。正确的使用reduce 就是要正确的写好这个函数,通常这个函数要满足一下,几点要求。

  1, 这个函数至少要接受两个参数进行计算,一个参数是累计值,一个参数是数组的每一个元素

  2, 这个函数必须要有返回值,因为要用它进行下一步的运算,并且,必须返回一个由参数进行计算的得到结果值,最后返回的值,还是要和数组中的元素类型相同,这还是因为它要进行下一步的运算。

  3, 初始的结果值,可以由第三个参数进行传递,也可以不传,如果不传的话,初始的累计值默认为第一个参数。

数组中的reduce 函数理解的更多相关文章

  1. JS中的reduce函数

    海纳百川,有容乃大 定义: reduce()方法接受一个函数作为累加器,数组中的每个值(从左向右)开始缩减,最终计算为一个值.对空数组是不会执行回调函数的. 案例: 计算数组总和: var num = ...

  2. python中filter(),reduce()函数

    filter()函数 是 Python 内置的另一个有用的高阶函数,filter()函数接收一个函数 和一个list,这个函数的作用是对每个元素进行判断,返回 True或 False,filter() ...

  3. PHP:第四章——数组中的排序函数

    <pre> <?php header("Content-Type:text/html;charset=utf-8"); //1) /*sort - 对数组进行升序 ...

  4. 数组中的reduce

    reduce方法第一次对我的感觉是很鸡肋,但是深入了解,才发现其中的奥妙,是个非常强大且实用的方法 var arr = [1,2,3,4,5,6,7]; var sum = arr.reduce( ( ...

  5. python中的reduce函数

    python中的reduce   python中的reduce内建函数是一个二元操作函数,他用来将一个数据集合(链表,元组等)中的所有数据进行下列操作:用传给reduce中的函数 func()(必须是 ...

  6. 【C++函数题目】重载求数组中最小值的函数

    题目来源:https://acm.ujn.edu.cn Time Limit: 1 Sec  Memory Limit: 128 MB Description 写一个函数名称为miniElement( ...

  7. Pychram中使用reduce()函数报错:Unresolved reference 'reduce'

    python3不能直接使用reduce()函数,因为reduce() 函数已经被从全局名字空间里移除了,它现在被放置在fucntools 模块里,所以要使用reduce函数得先饮用fucntools ...

  8. functools 中的 reduce 函数基本写法

    reduce 返回的往往是一整个可迭代对象的 操作结果 reduce(函数,可迭代对象) 注:lambda x,y 两个参数 2020-05-04

  9. Python中的reduce()函数

    reduce()函数也是Python内置的一个高阶函数.reduce()函数接收的参数和 map()类似,一个函数 f,一个list,但行为和 map()不同,reduce()传入的函数 f 必须接收 ...

随机推荐

  1. SQL优化 MySQL版 - 索引分类、创建方式、删除索引、查看索引、SQL性能问题

    SQL优化 MySQL版  - 索引分类.创建方式.删除索引.查看索引.SQL性能问题 作者 Stanley 罗昊 [转载请注明出处和署名,谢谢!] 索引分类 单值索引 单的意思就是单列的值,比如说有 ...

  2. Tomcat 对 HTTP 协议的实现(下)

    在<Tomcat 对 HTTP 协议的实现(上)>一文中,对请求的解析进行了分析,接下来对 Tomcat 生成响应的设计和实现继续分析.本文首发于(微信公众号:顿悟源码) 一般 Servl ...

  3. Shell从入门到精通进阶之四:流程控制

    流程控制是改变程序运行顺序的指令. 4.1 if语句 4.1.1 单分支 if 条件表达式; then 命令 fi 示例: #!/bin/bash N=10 if [ $N -gt 5 ]; then ...

  4. 自定义GridControl编辑器

    本文版权归博主 惊梦无痕 所有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作.SourceLink 鉴于网上的针对GridControl的一些代码比较凌乱,且功能分散,故将整理过的代码分享出来 ...

  5. electron开发客户端注意事项(兼开源个人知识管理工具“想学吗”)

    窗口间通信的问题 electron窗口通信比nwjs要麻烦的多 electron分主进程和渲染进程,渲染进程又分主窗口的渲染进程和子窗口的渲染进程 主窗口的渲染进程给子窗口的渲染进程发消息 subWi ...

  6. C# 委托链(多播委托)

    委托既可以封装一个方法,又可以对同一类型的方法进行封装,它就是多播委托 using System; using System.Collections.Generic; using System.Lin ...

  7. CMD命令讲解(一)SC

    参考网站:https://technet.microsoft.com/en-us/library/bb490995.aspx 备注:网站内容是翻译得来,源网站在上面 SC 与服务控制器和已安装的服务进 ...

  8. ASP.NET Core 部署IIS及 OFFSET 附近有语法错误解决

    今天自己开发了一个订机票的微信公众号,功能基本已经完成,然后想部署到服务器实际测试下.结果部署上去出现各种问题.先安装asp.net core模块,然后发现数据库并不像在开发时一样,执行ef的命令行语 ...

  9. Windows环境下使用pip install安装lxml库

    lxml是Python语言和XML以及HTML工作的功能最丰富和最容易使用的库.lxml是为libxml2和libxslt库的一个Python化的绑定.它与众不同的地方是它兼顾了这些库的速度和功能完整 ...

  10. C# Socket网络编程

    晚上利用空闲时间,用Socket做了一些小功能. 功能如下: a.聊天 b.传文件 c.抖动好友 主界面: 服务器 客户端 操作步骤: 服务器(测试环境的IP地址为:192.168.92.111,视情 ...