reduce方法的妙用

语法

Array.reduce(callback[, initialValue])
参数:
callback
执行在每个数组元素上的方法,带入参数:

  • 累加器
    累加器会累加callback返回的值。
  • 当前值
    当前传入的数组元素
  • 当前元素的index(Optional)
    当前传入的数组元素的index。如果提供了初始值从0开始,否则从1开始
  • 当前数组(Optional)
    当前数组执行reduce的数组
  • 初始值(Optional)
    第一次执行callback时带入的参数,如果没有提供则使用第一个数组元素。空数组执行reduce()且没有提供初始值则会报错。

最后返回执行后的value


比对范例

数组 arr = [1,2,3,4] 求数组的和

// forEach-实现
var arr = [1,2,3,4],
    sum = 0;
arr.forEach(function(e){sum += e;}); // sum = 10  just for demo

// map 实现
var arr = [1,2,3,4],
    sum = 0;
arr.map(function(obj){sum += obj});// return undefined array.
// sum = 10  just for demo

// reduce实现
var arr = [1,2,3,4];

arr.reduce(function(pre,cur){return pre + cur}); // return 10

进阶用法

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

ruduce可以完成多维度的数据叠加。将最外层reduce的callback封装为一个方法,在需要使用时调用。封装的方法内部去完成子问题(分治法)

// 例子2
// 遍历统计一串字符串中每个字母出现的次数
var arrString = 'abcdaabc';

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

koa中的源码实现only

only新建并返回一个obj对象中存在的keys的object对象

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;
  }, {});
};
var a = {
    env : 'development',
    proxy : false,
    subdomainOffset : 2
}
only(a,['env','proxy'])   // {env:'development',proxy : false}

引申:遍历方法的比较

  1. for语句
    for(var i = 0, len = arr.length; i < len; i++){ console.log(arr[i]) }
    这是标准for循环的写法也是最传统的语句,字符串也支持,定义一个变量i作为索引,以跟踪访问的位置,len是数组的长度,条件就是i不能超过len。

  2. for-in 语句
    for (var key in obj) { console.log(obj[key]) }
    一般会使用for-in来遍历对象的属性的,不过属性需要 enumerable,才能被读取到。

  3. for-of(ES6语句)
    for (item of arr) { console.log(item) }
    for-of语句在可迭代对象(包括 Array,Map,Set,String,TypedArray,arguments 对象等等)上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句。只要是一个iterable的对象,就可以通过for-of来迭代。
    for-of 和 for-in 的区别
    for-in 语句以原始插入顺序迭代对象的可枚举属性。for-in会把继承链的对象属性都会遍历一遍,所以会更花时间。
    for-of 语句只遍历可迭代对象的数据。

↓↓↓↓↓↓数组方法↓↓↓↓↓↓

  1. forEach 语句
    arr.forEach(function(item) { console.log(item); })
    forEach 方法对数组的每个元素执行一次提供的CALLBACK函数,可以用来把一个函数套用在一个数组中的每个元素上,forEach为每个数组元素执行callback函数只可用于数组。已删除(使用delete方法等情况)或者未初始化的项将被跳过(但不包括那些值为 undefined 的项,例如在稀疏数组上)。不像map() 或者reduce() ,它总是返回 undefined值,并且不可链式调用。典型用例是在一个链的最后执行副作用。

  2. map 方法 (不改变原数组)
    var firearr = arr.map(current => current * 5)
    map 方法会给原数组中的每个元素都按顺序调用一次 callback 函数。callback 每次执行后的返回值(包括 undefined)组合起来形成一个新数组。 callback 函数只会在有值的索引上被调用;那些从来没被赋过值或者使用 delete 删除的索引则不会被调用。让数组通过某种计算产生一个新数组,影射成一个新的数组。

  3. reduce 方法
    让数组中的前项和后项做某种计算,并累计最终值。

  4. filter 方法 (不改变原数组)
    var morearr = arr.filter(function (number) { return number > 3 })
    filter 为数组中的每个元素调用一次 callback 函数,并利用所有使得 callback 返回 true 或 等价于 true 的值 的元素创建一个新数组。callback 只会在已经赋值的索引上被调用,对于那些已经被删除或者从未被赋值的索引不会被调用。那些没有通过 callback 测试的元素会被跳过,不会被包含在新数组中。筛选出过滤出数组中符合条件的项,组成新数组。

  5. every 方法
    var result = arr.every(function (item, index) { return item > 0 })
    every 方法为数组中的每个元素执行一次 callback 函数,直到它找到一个使 callback 返回 false(表示可转换为布尔值 false 的值)的元素。如果发现了一个这样的元素,every 方法将会立即返回 false。否则,callback 为每一个元素返回 true,every 就会返回 true。检测数组中的每一项是否符合条件,如果每一项都符合条件,就会返回true,否则返回false,有点像遍历数组且操作callback。只会为那些已经被赋值的索引调用。不会为那些被删除或从来没被赋值的索引调用。

  6. some 方法
    var result = arr.some(function (item,index) { return item > 3 })
    some 为数组中的每一个元素执行一次 callback 函数,直到找到一个使得 callback 返回一个“真值”(即可转换为布尔值 true 的值)。如果找到了这样一个值,some 将会立即返回 true。否则,some 返回 false。callback 只会在那些”有值“的索引上被调用,不会在那些被删除或从来未被赋值的索引上调用。检查数组中是否有某些项符号条件,如果有一项就返回true,否则返回false,有点像遍历数组或者操作。
    every 和 some 不完全属于数组操作方法
    every 和 some 都是判断条件直接返回整个数组Boolean类型的方法。every速度会比some快很多。

    一张图展示JavaScript数组方法


参考

数组reduce方法的高级技巧
JS进阶篇--JS数组reduce()方法详解及高级技巧
JS 循环遍历方法的对比

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,284评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,115评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,614评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,671评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,699评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,562评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,309评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,223评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,668评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,859评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,981评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,705评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,310评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,904评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,023评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,146评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,933评论 2 355

推荐阅读更多精彩内容