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作为累加器。实际上根据这个回调函数,可以实现不同的功能,比如说,对数组项求合;将多个数组合并到一个数组等等。甚至配合数组其他的方法你还可以做更多功能的处理。如果感兴趣的话不仿尝试一二。
初学者学习笔记,如有不对,还希望高手指点。如有造成误解,还希望多多谅解。
大漠
如需转载,烦请注明出处:http://www.w3cplus.com/javascript/array-part-8.html
JavaScript学习笔记:数组reduce()和reduceRight()方法的更多相关文章
- Java程序猿的JavaScript学习笔记(9—— jQuery工具方法)
计划按例如以下顺序完毕这篇笔记: Java程序猿的JavaScript学习笔记(1--理念) Java程序猿的JavaScript学习笔记(2--属性复制和继承) Java程序猿的JavaScript ...
- JavaScript学习笔记-数组(1)
数组是值的有序集合.每个值叫做一个元素,而每个元素在数组中有一个位置,以数字表示,称为索引.JavaScript数组是无类型的:数组元素可以是任意类型,并且同一个数组中的不同元素也可能有不同的类型.数 ...
- JavaScript学习笔记-数组
数组 数组中的每个元素的位置是索引,索引是基于32位的由0开始的数值,最大索引为(2的32次方-2),最大长度为(2的32次方-3) 数组是无类型的:元素可为任意类型:动态的:可根据需要自动增长.缩减 ...
- JavaScript学习笔记-用于模式匹配的String方法
用于模式匹配的String方法: String支持4种使用正则表达式的方法: seach()用于检索,参数是一个正则表达式,返回第一个与之匹配的子串的位置,找不到则返回-1,如 ...
- JavaScript学习笔记- 正则表达式常用字符集及方法
正则表达式修饰符(修饰符 可以在全局搜索中不区分大小写) i(ignoreCase)执行对大小写不敏感的匹配 g (global) 执行全局匹配(查找所有匹配而非在找到第一个匹配后停止) m( ...
- JavaScript学习笔记——数组
javascript数组数组是一个可以存储 一组 或是 一系列 相关数据 的 容器. 一.为什么要使用数组. (1)为了解决大量相关数据的存储和使用的问题. (2)模拟真是的世界. 二.如何创建数组 ...
- JavaScript学习笔记(1)字符串方法
字符串方法 length 属性返回字符串的长度 var txt = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; var sln = txt.length; inde ...
- Java程序猿的JavaScript学习笔记(5——prototype和Object内置方法)
计划按例如以下顺序完毕这篇笔记: Java程序猿的JavaScript学习笔记(1--理念) Java程序猿的JavaScript学习笔记(2--属性复制和继承) Java程序猿的JavaScript ...
- Java程序猿的JavaScript学习笔记(8——jQuery选择器)
计划按例如以下顺序完毕这篇笔记: Java程序猿的JavaScript学习笔记(1--理念) Java程序猿的JavaScript学习笔记(2--属性复制和继承) Java程序猿的JavaScript ...
随机推荐
- ANDROID 开机启动VNC SERVER
ANDROID 开机启动VNC SERVER 背景信息: 最近在做一个项目,在项目需求中有这么一项“要把VNC SERVER 添加到android里并让其开机自启动”.其实做这个项目也挺缚手缚脚的,因 ...
- Taurus.MVC
开源:Taurus.MVC 框架 为什么要创造Taurus.MVC: 记得被上一家公司忽悠去负责公司电商平台的时候,情况是这样的: 项目原版是外包给第三方的,使用:WebForm+NHibernate ...
- JavaScript事件处理
客户端javascript程序采用了异步事件驱动程序,在这种程序设计风格下,当文档,浏览器,元素,或与之相关的对象发生某些有趣的事件时,web浏览器就会产生事件.事件本身不是javascript对象. ...
- Android高德地图开发具体解释
这段时间开发的时候用到了高德地图,对高德地图开发有心得体会,如今分享给大家.对我开发过百度地图的我来说,整体来说高德地图Demo,没有百度解说的具体 个人更偏向于使用百度地图,可是没办发,项目须要使用 ...
- Linux系统编程(23)——信号的阻塞
实际执行信号的处理动作称为信号递达(Delivery),信号从产生到递达之间的状态,称为信号未决(Pending).进程可以选择阻塞(Block)某个信号.被阻塞的信号产生时将保持在未决状态,直到进程 ...
- nginx监听端口和反向代理端口的权限问题
Linux的SELinux安全性控制除作用于文件系统外还作用于端口,这使得那些作为服务启动的进程只能在规定的几个端口上监听.为叙述方便我们称之为受控端口. nginx监听端口 要查看当前有哪些受控端口 ...
- javac命令详解(下)
摘自http://blog.csdn.net/hudashi/article/details/7058999 javac命令详解(下) -ver ...
- Jekins安装
1. Jekins支持多系统:windows, mac,linux 2. Jekins安装方式有三种:直接war文件安装,安装包安装,将war文件放到web容器安装 3. 在windows下安装 a. ...
- 水池数目(DFS)
水池数目 时间限制:3000 ms | 内存限制:65535 KB 难度:4 描述 南阳理工学院校园里有一些小河和一些湖泊,现在,我们把它们通一看成水池,假设有一张我们学校的某处的地图,这个地 ...
- 【转】Java与C#语言级比较
原文链接:http://www.harding.edu/fmccown/java_csharp_comparison.html Java 程序结构 C# package hello;public cl ...