JavaScript之数组reduce()和reduceRight()方法学习讲解
javascript之数组reduce()和reduceright()方法学习讲解
很多时候需要累加数组项的得到一个值(比如说求和)。如果你碰到一个类似的问题,你想到的方法是什么呢?会不会和我一样,想到的就是使用for或while循环,对数组进行迭代,依次将他们的值加起来。比如:
var arr = [1,2,3,4,5,6]; array.prototype.sum = function (){ var sumresult = 0; for (var i = 0; i < this.length; i++) { sumresult += parseint(this[i]); } return sumresult; } arr.sum(); // 21
或者
var arr = [1,2,3,4,5,6]; array.prototype.sum = function () { var sumresult = 0; var i = this.length; while (i--) { sumresult += parseint(this[i]); } return sumresult; } arr.sum(); // 21
那他们是不是最好的方案呢?先来看看他们所耗时间。
// 测试for和while循环实现数组求和的性能 var arr = [1,2,3,4,5,6]; // for循环 console.time("forloop"); array.prototype.forloop = function (){ for (var i = 0; i < 10000; i++) { var sumresult = 0; for (var j = 0; j < this.length; j++) { sumresult += parseint(this[j]); } } return sumresult; } arr.forloop(); console.log('最终的值:' + arr.forloop()); // 21 console.timeend("forloop"); // 54.965ms
再来看看while循环所用时间:
var arry = [1,2,3,4,5,6]; console.time("whileloop"); array.prototype.whileloop = function () { for (var i = 0; i < 10000; i++) { var sumresult = 0; for (var j = 0; j < this.length; j++) { sumresult += parseint(this[j]); } } return sumresult; } arry.whileloop(); console.log('最终的值:' + arry.whileloop()); // 21 console.timeend("whileloop"); // 53.056ms
看看对比结果
循环类型 | 最终值(和) | 所费时间 |
---|---|---|
for | 21 | 54.965ms |
while | 21 | 53.056ms |
备注:数组[1,2,3,4,5,6]做了10000次循环的累加。
虽然上面使用for和while都能实现需要的效果,但在javascript中有没有更好的方案呢?回答是肯定的,在javascript中(esmascript 5)提供了另外两个数组的方法reduce()和reduceright(),这两个数组会迭代数组的所有数组项,然后返回一个最终值。接下来的内容,主要来学习这两种方法。
reduce()方法
reduce()方法接收一个函数callbackfn作为累加器(accumulator),数组中的每个值(从左到右)开始合并,最终为一个值。
语法
array.reduce(callbackfn,[initialvalue])
reduce()方法接收callbackfn函数,而这个函数包含四个参数:
function callbackfn(prevalue,curvalue,index,array){}
prevalue: 上一次调用回调返回的值,或者是提供的初始值(initialvalue)
curvalue: 数组中当前被处理的数组项
index: 当前数组项在数组中的索引值
array: 调用reduce()方法的数组
而initialvalue作为第一次调用callbackfn函数的第一个参数。
reduce()方法为数组中的每一个元素依次执行回调函数callbackfn,不包括数组中被删除或从未被赋值的元素,接受四个参数:初始值(或者上一次回调函数的返回值),当前元素值,当前索引,调用reduce()的数组。
回调函数第一次执行时,prevalue和curvalue可以是一个值,如果initialvalue在调用reduce()时被提供,那么第一个prevalue等于initialvalue,并且curvalue等于数组中的第一个值;如果initialvalue未被提供,那么prevalue等于数组中的第一个值,`curvalue等于数组中的第二个值。
来看一个示例:
var arr = [0,1,2,3,4]; arr.reduce(function (prevalue,curvalue,index,array) { return prevalue + curvalue; }); // 10
示例中的回调函数被执行四次,每次参数和返回的值如下:
prevalue | curvalue | index | array | 返回值 | |
---|---|---|---|---|---|
第一次回调 | 0 | 1 | 1 | [0,1,2,3,4] | 1 |
第二次回调 | 1 | 2 | 2 | [0,1,2,3,4] | 3 |
第三次回调 | 3 | 3 | 3 | [0,1,2,3,4] | 6 |
第四次回调 | 6 | 4 | 4 | [0,1,2,3,4] | 10 |
上面的示例reduce()方法没有提供initialvalue初始值,接下来再上面的示例中,稍作修改,提供一个初始值,这个值为5。这个时候reduce()方法会执行五次回调,每次参数和返回的值如下:
var arr = [0,1,2,3,4]; arr.reduce(function (prevalue,curvalue,index,array) { return prevalue + curvalue; }, 5); //15
prevalue | curvalue | index | array | 返回值 | |
---|---|---|---|---|---|
第一次回调 | 5 | 0 | 0 | [0,1,2,3,4] | 5 |
第二次回调 | 5 | 1 | 1 | [0,1,2,3,4] | 6 |
第三次回调 | 6 | 2 | 2 | [0,1,2,3,4] | 8 |
第四次回调 | 8 | 3 | 3 | [0,1,2,3,4] | 11 |
第五次回调 | 11 | 4 | 4 | [0,1,2,3,4] | 15 |
这样一来,不用多说,应该都知道,可以使用reduce()实现数组求和的功能。如:
var arr = [1,2,3,4,5,6]; array.prototype.sum = function (){ var sumresult = 0; return this.reduce(function (prevalue, curvalue) { return sumresult = prevalue + curvalue; }); return sumresult; } arr.sum(); // 21
回到文章的前面,来看看使用reduce()方法对数组求和,需要多少时间:
var arr = [1,2,3,4,5,6]; console.time("ruduce"); array.prototype.ruducesum = function (){ for (var i = 0; i < 10000; i++) { return this.reduce (function (prevalue, curvalue) { return prevalue + curvalue; }); } } arr.ruducesum(); console.log('最终的值:' + arr.ruducesum()); // 21 console.timeend("ruduce"); // 0.417ms
同时看看所费时间的对比:
循环类型 | 最终值(和) | 所费时间 |
---|---|---|
for | 21 | 54.965ms |
while | 21 | 53.056ms |
reduce | 21 | 0.417ms |
在chrome下,每次执行的数据都会略有不同,但可以明显的看出reduce()对数组项求和所费时间是最短的。
reduceright()方法
reduceright()方法的功能和reduce()功能是一样的,不同的是reduceright()从数组的末尾向前将数组中的数组项做累加。
reduceright()首次调用回调函数callbackfn时,prevvalue和curvalue可以是两个值之一。如果调用reduceright()时提供了initialvalue参数,则prevvalue等于initialvalue,curvalue等于数组中的最后一个值。如果没有提供initialvalue参数,则prevvalue等于数组最后一个值,curvalue等于数组中倒数第二个值。
来看实例:
var arr = [0,1,2,3,4]; arr.reduceright(function (prevalue,curvalue,index,array) { return prevalue + curvalue; }); // 10
回调将会被调用四次,每次调用的参数及返回值如下:
prevalue | curvalue | index | array | 返回值 | |
---|---|---|---|---|---|
第一次回调 | 4 | 3 | 3 | [0,1,2,3,4] | 7 |
第二次回调 | 7 | 2 | 2 | [0,1,2,3,4] | 9 |
第三次回调 | 9 | 1 | 1 | [0,1,2,3,4] | 10 |
第四次回调 | 10 | 0 | 0 | [0,1,2,3,4] | 10 |
如果提供一个初始值initialvalue为5:
var arr = [0,1,2,3,4]; arr.reduceright(function (prevalue,curvalue,index,array) { return prevalue + curvalue; }, 5); // 15
回调将会被调用五次,每次调用的参数及返回的值如下:
prevalue | curvalue | index | array | 返回值 | |
---|---|---|---|---|---|
第一次回调 | 5 | 4 | 4 | [0,1,2,3,4] | 9 |
第二次回调 | 9 | 3 | 3 | [0,1,2,3,4] | 12 |
第三次回调 | 12 | 2 | 2 | [0,1,2,3,4] | 14 |
第四次回调 | 14 | 1 | 1 | [0,1,2,3,4] | 15 |
第五次回调 | 15 | 0 | 0 | [0,1,2,3,4] | 15 |
同样的,可以对一个数组求和,也可以使用reduceright()方法:
var arr = [1,2,3,4,5,6]; console.time("ruduceright"); array.prototype.ruducerightsum = function (){ for (var i = 0; i < 10000; i++) { return this.reduceright (function (prevalue, curvalue) { return prevalue + curvalue; }); } } arr.ruducerightsum(); console.log('最终的值:' + arr.ruducesum()); // 21 console.timeend("ruduceright"); // 5.725ms
总结
reduce()和reduceright()两个方法功能都是类似的,可以让数组调用一个回调函数callbackfn作为累加器。实际上根据这个回调函数,可以实现不同的功能,比如说,对数组项求合;将多个数组合并到一个数组等等。甚至配合数组其他的方法你还可以做更多功能的处理。如果感兴趣的话不仿尝试一二。
推荐阅读
-
JavaScript之数组reduce()和reduceRight()方法学习讲解
-
JavaScript之数组reduce()和reduceRight()方法学习讲解
-
javascript学习之字符串方法、数组方法介绍
-
JavaScript学习笔记之取数组中最大值和最小值_javascript技巧
-
Javascript学习笔记之数组的遍历和 length 属性_基础知识
-
JavaScript学习笔记之数组求和方法_javascript技巧
-
JavaScript学习笔记之取数组中最大值和最小值_javascript技巧
-
Javascript学习笔记之数组的遍历和 length 属性_基础知识
-
JavaScript学习笔记之数组求和方法_javascript技巧
-
javascript学习之字符串方法、数组方法介绍