第一次见到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. 秋招提前批小结(CVTE一面挂、阿里三面挂)

    7月27日:CVTE一面 30分钟(挂) 1.自我介绍 2.有没有做过JavaWeb相关的项目?你觉得难点在哪里呢? 3.你这个博客系统有没有加权限系统?如果被拦截封包获取了账号密码怎么办?(没加,凉 ...

  2. k8s源码分析准备工作 - 源码准备

    本文原始地址:https://farmer-hutao.github.io/k8s-source-code-analysis/ 项目github地址:https://github.com/farmer ...

  3. 图片与Base64的转换

    图片转为Base64 // 图片转化成base64字符串 public static String GetImageStr() {// 将图片文件转化为字节数组字符串,并对其进行Base64编码处理 ...

  4. 单机Qps上限是多少?

    现在这个年代,你要是不懂高并发,你都不好意思说自己是搞互联网的! 一.什么是并发,什么是高并发 并发,两个及以上的行为一起发生,比如你一边吃饭一边看电视 高并发,多个行为(至于是多少,这个没有定数,你 ...

  5. Jmeter调用自定义jar包

    一. 场景 在测试过程中, 可能需要调用第三方jar包来生成测试数据或者使用java工具类来实现业务场景, 普遍的做法是手动调用jar包, 再把这些值赋给jmeter中的某个参数, 以满足业务测试需求 ...

  6. Jenkins分布式部署配置

    为什要使用Jenkins分布式? 利用jenkins分布式来构建job,当job量足够大的时候,可以有效的缓解jenkins-master上的压力,提高并行job数量, 减少job处于pending状 ...

  7. C#枚举(Enum)小结

    枚举概念 枚举类型(也称为枚举)提供了一种有效的方式来定义可能分配给变量的一组已命名整数常量.该类型使用enum关键字声明. 示例代码1 enum Day { Sunday, Monday, Tues ...

  8. android – 无法解析AppCompatActivity

    用SVN获取了别人写的代码后出现 android – 无法解析AppCompatActivity 最后解决办法: 在模版的build.gradle文件中将依赖性的版本号更改了 ,同步后,再改过来就ok ...

  9. 【记录】使用在线KMS激活win10系统

    摘要 网上一些激活工具可能捆绑了木马.病毒.使用激活工具有风险.使用在线KMS来激活系统则没有这个风险.(自测至发布日期仍然可用) (有能力的请支持正版windows系统) 将kms服务器地址设置为k ...

  10. 【推荐】Pencil原型设计工具

    官网:http://pencil.evolus.vn/ 试用了一下,确实感觉很好用,整体体验上是一种“舒畅”的感觉,真心点赞推荐.整体功能上没有任何多余的东西,让人感觉上手就能用.虽然个人英语水平不咋 ...