详解JS数组Reduce()方法详解及高级技巧


Posted in Javascript onAugust 18, 2017

基本概念

reduce() 方法接收一个函数作为累加器(accumulator),数组中的每个值(从左到右)开始缩减,最终为一个值。

reduce 为数组中的每一个元素依次执行回调函数,不包括数组中被删除或从未被赋值的元素,接受四个参数:初始值(或者上一次回调函数的返回值),当前元素值,当前索引,调用 reduce 的数组。

语法:

arr.reduce(callback,[initialValue])
  • callback (执行数组中每个值的函数,包含四个参数)
  • previousValue (上一次调用回调返回的值,或者是提供的初始值(initialValue))
  • currentValue (数组中当前被处理的元素)
  • index (当前元素在数组中的索引)
  • array (调用 reduce 的数组)
  • initialValue (作为第一次调用 callback 的第一个参数。)

简单应用

例1:

var items = [10, 120, 1000];
// our reducer function
var reducer = function add(sumSoFar, item) { return sumSoFar + item; };
// do the job
var total = items.reduce(reducer, 0);
console.log(total); // 1130

可以看出,reduce函数根据初始值0,不断的进行叠加,完成最简单的总和的实现。

reduce函数的返回结果类型和传入的初始值相同,上个实例中初始值为number类型,同理,初始值也可为object类型。

例2:

var items = [10, 120, 1000];
// our reducer function
var reducer = function add(sumSoFar, item) {
 sumSoFar.sum = sumSoFar.sum + item;
 return sumSoFar;
};
// do the job
var total = items.reduce(reducer, {sum: 0});
console.log(total); // {sum:1130}

进阶应用

使用reduce方法可以完成多维度的数据叠加。如上例中的初始值{sum: 0},这仅仅是一个维度的操作,如果涉及到了多个属性的叠加,如{sum: 0,totalInEuros: 0,totalInYen: 0},则需要相应的逻辑进行处理。

在下面的方法中,采用分而治之的方法,即将reduce函数第一个参数callback封装为一个数组,由数组中的每一个函数单独进行叠加并完成reduce操作。所有的一切通过一个manager函数来管理流程和传递初始参数。

var manageReducers = function(reducers) {
 return function(state, item) {
  return Object.keys(reducers).reduce(
   function(nextState, key) {
    reducers[key](state, item);
    return state;
   },
   {}
  );
 }
};

上面就是manager函数的实现,它需要reducers对象作为参数,并返回一个callback类型的函数,作为reduce的第一个参数。在该函数内部,则执行多维的叠加工作(Object.keys())。

通过这种分治的思想,可以完成目标对象多个属性的同时叠加,完整代码如下:

var reducers = { 
 totalInEuros : function(state, item) {
  return state.euros += item.price * 0.897424392;
 },
 totalInYen : function(state, item) {
  return state.yens += item.price * 113.852;
 }
};
var manageReducers = function(reducers) {
 return function(state, item) {
  return Object.keys(reducers).reduce(
   function(nextState, key) {
    reducers[key](state, item);
    return state;
   },
   {}
  );
 }
};
var bigTotalPriceReducer = manageReducers(reducers);
var initialState = {euros:0, yens: 0};
var items = [{price: 10}, {price: 120}, {price: 1000}];
var totals = items.reduce(bigTotalPriceReducer, initialState);
console.log(totals);

在来一个例子:

某同学的期末成绩如下表示

var result = [
  {
    subject: 'math',
    score: 88
  },
  {
    subject: 'chinese',
    score: 95
  },
  {
    subject: 'english',
    score: 80
  }
];

如何求该同学的总成绩?

var sum = result.reduce(function(prev, cur) {
  return cur.score + prev;
}, 0);

假设该同学因为违纪被处罚在总成绩总扣10分,只需要将初始值设置为-10即可。

var sum = result.reduce(function(prev, cur) {
  return cur.score + prev;
}, -10);

我们来给这个例子增加一点难度。假如该同学的总成绩中,各科所占的比重不同,分别为50%,30%,20%,我们应该如何求出最终的权重结果呢?

解决方案如下:

var dis = {
  math: 0.5,
  chinese: 0.3,
  english: 0.2
}
var sum = result.reduce(function(prev, cur) {
  return cur.score + prev;
}, -10);
var qsum = result.reduce(function(prev, cur) {
  return cur.score * dis[cur.subject] + pre;
}, 0)
console.log(sum, qsum);

再看一个例子,如何知道一串字符串中每个字母出现的次数?

var arrString = 'abcdaabc';
arrString.split('').reduce(function(res, cur) {
  res[cur] ? res[cur] ++ : res[cur] = 1
  return res;
}, {})

由于可以通过第二参数设置叠加结果的类型初始值,因此这个时候reduce就不再仅仅只是做一个加法了,我们可以灵活的运用它来进行各种各样的类型转换,比如将数组按照一定规则转换为对象,也可以将一种形式的数组转换为另一种形式的数组,大家可以动手去尝试一样。

[1, 2].reduce(function(res, cur) { 
  res.push(cur + 1); 
  return res; 
}, [])

koa的源码中,有一个only模块,整个模块就一个简单的返回reduce方法操作的对象:

var only = function(obj, keys){
 obj = obj || {};
 if ('string' == typeof keys) keys = keys.split(/ +/);
 return keys.reduce(function(ret, key){
  if (null == obj[key]) return ret;
  ret[key] = obj[key];
  return ret;
 }, {});
};

通过对reduce概念的理解,这个模块主要是想新建并返回一个obj对象中存在的keys的object对象。

var a = {
  env : 'development',
  proxy : false,
  subdomainOffset : 2
}
only(a,['env','proxy'])  // {env:'development',proxy : false}

总结

以上所述是小编给大家介绍的详解JS数组Reduce()方法详解及高级技巧,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
一个js导致的jquery失效问题的解决方法
Nov 27 Javascript
js如何调用qq互联api实现第三方登录
Mar 28 Javascript
Enter回车切换输入焦点实现思路与代码兼容各大浏览器
Sep 01 Javascript
JavaScript、tab切换完整版(自动切换、鼠标移入停止、移开运行)
Jan 05 Javascript
JS设置时间无效问题的解决办法
Feb 18 Javascript
canvas实现简易的圆环进度条效果
Feb 28 Javascript
通过npm引用的vue组件使用详解
Mar 02 Javascript
老生常谈js-react组件生命周期
May 02 Javascript
详解Vue 动态组件与全局事件绑定总结
Nov 11 Javascript
浅谈Fetch 数据交互方式
Dec 20 Javascript
vue element-ui table组件动态生成表头和数据并修改单元格格式 父子组件通信
Aug 15 Javascript
H5 js点击按钮复制文本到粘贴板
Nov 19 Javascript
javascript将url解析为json格式的两种方法
Aug 18 #Javascript
Vue组件选项props实例详解
Aug 18 #Javascript
浅谈angular4 ng-content 中隐藏的内容
Aug 18 #Javascript
Node.JS更改Windows注册表Regedit的方法小结
Aug 18 #Javascript
浅谈Angular2 ng-content 指令在组件中嵌入内容
Aug 18 #Javascript
Vue中引入样式文件的方法
Aug 18 #Javascript
jQuery+HTML5实现WebGL高性能烟花绽放动画效果【附demo源码下载】
Aug 18 #jQuery
You might like
PHP register_shutdown_function函数的深入解析
2013/06/03 PHP
PHP的mysqli_query参数MYSQLI_STORE_RESULT和MYSQLI_USE_RESULT的区别
2014/09/29 PHP
WordPress中注册菜单与调用菜单的方法详解
2015/12/18 PHP
php安装php_rar扩展实现rar文件读取和解压的方法
2016/11/17 PHP
PHP基于关联数组20行代码搞定约瑟夫问题示例
2017/11/07 PHP
function foo的原型与prototype属性解惑
2010/11/19 Javascript
javascript定时保存表单数据的代码
2011/03/17 Javascript
灵活应用js调试技巧解决样式问题的步骤分享
2012/03/15 Javascript
javascript查询字符串参数的方法
2015/01/28 Javascript
js实现带关闭按钮始终显示在网页最底部工具条的方法
2015/03/02 Javascript
纯javascript模仿微信打飞机小游戏
2015/08/20 Javascript
jQuery+ajax简单实现文件上传的方法
2016/06/03 Javascript
JS实现将数字金额转换为大写人民币汉字的方法
2016/08/02 Javascript
微信小程序 自定义对话框实例详解
2017/01/20 Javascript
利用vueJs实现图片轮播实例代码
2017/06/03 Javascript
10个最优秀的Node.js MVC框架
2017/08/24 Javascript
JS实现简单获取最近7天和最近3天日期的方法
2018/04/18 Javascript
一个简单的node.js界面实现方法
2018/06/01 Javascript
浅谈VueJS SSR 后端绘制内存泄漏的相关解决经验
2018/12/20 Javascript
Vue-axios-post数据后端接不到问题解决
2020/01/09 Javascript
JS原型和原型链原理与用法实例详解
2020/02/05 Javascript
windows下create-react-app 升级至3.3.1版本踩坑记
2020/02/17 Javascript
[00:34]DOTA2上海特级锦标赛 VG战队宣传片
2016/03/04 DOTA
python和shell变量互相传递的几种方法
2013/11/20 Python
python实现dict版图遍历示例
2014/02/19 Python
Python OpenCV视频截取并保存实现代码
2019/11/30 Python
Python控制台输出时刷新当前行内容而不是输出新行的实现
2020/02/21 Python
python微信公众号开发简单流程实现
2020/03/09 Python
Python程序慢的重要原因
2020/09/04 Python
巴黎欧莱雅法国官网:L’Oreal Paris
2019/04/30 全球购物
GetYourGuide台湾:预订旅游活动、景点和旅游项目
2019/06/10 全球购物
Myprotein比利时官方网站:欧洲第一运动营养品牌
2020/10/04 全球购物
在C#中如何实现多态
2014/07/02 面试题
校运会广播稿100字
2014/01/27 职场文书
营销策划分析:怎么策划才能更好销量产品?
2019/09/04 职场文书
MySQL修炼之联结与集合浅析
2021/10/05 MySQL