第一次见到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. django-restframework之缓存系统

    django-restframework之缓存系统 一 前言 一 为什么需要缓存 在动态网站中,用户所有的请求,服务器都会去数据库中进行相应的增.删.查.改,渲染模块,执行业务逻辑,最后生成用户看到的 ...

  2. keil进阶教程

    前言 keil只懂得创建软件工程是远远不够的,如果要想顺心使用,应该要懂得部分配置,这样使用心情顺畅,码代码也会越发高效. 设置字号字体 编辑点击编辑菜单,会出现很多子目录,找到配置,点击进入设置页面 ...

  3. [Vue] vue中setInterval的问题

    vue中使用setInterval this.chatTimer = setInterval(() => { console.log(this.chatTimer); this.chatMsg( ...

  4. Springboot2注解使用Mybatis动态SQL

    1.简单SQL使用 //从***数据表获取统计数据 @Select("select count(*) from issues where issue_type = #{type}" ...

  5. JavaScript常用代码书写规范

    javascript 代码规范 代码规范我们应该遵循古老的原则:“能做并不意味着应该做”. 全局命名空间污染 总是将代码包裹在一个立即的函数表达式里面,形成一个独立的模块. 不推荐 , y = ; c ...

  6. Gulp 前端优化

    使用方法: 下载 node.js , https://nodejs.org/en/,并安装 msi 一下命令都属于 dos 命令 node -v,npm -v,检验是否下载成功(出现版本号) 将 np ...

  7. Windows有点腻了?不如试试Ubuntu.

    最近在接触Python. 因为担心环境会向Java一样,很容易影响当前的工作电脑. 所以准备搭建一台虚拟机,不过Windows的尺寸是在太大了.所以,选择安装Ubuntu. Ubuntu官方网站地址: ...

  8. app.config的坑

    C# C/S程序一般通过ConfigurationManager类来读取app.config,其中有个坑爹的地方是ConfigurationManager类自带缓存,就如Windows服务来说,除非重 ...

  9. mssql2008 r2 修改默认端口

    1.点击“开始”-“所有程序”-“Microsoft SQL Server 2008R2”-“配置工具”-“SQL Server配置管理器” 2.在打开的“SQL Server配置管理器”窗口中,在左 ...

  10. 'Attempt to create two animations for cell' iOS

    我是在对一个UITableView 一起进行 reloadRows和reloadSections 的操作的时候 出现的