felix-cao / Blog

A little progress a day makes you a big success!
31 stars 4 forks source link

JavaScript 数组实例方法 reduce 使用技巧 #210

Open felix-cao opened 2 years ago

felix-cao commented 2 years ago

Overview

语法: array.reduce(function(total, currentValue, currentIndex, arr), [initialValue]) reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。 reduce() 方法可以完成的功能,for 循环,或者 forEachmap 方法也可以完成, total 为累积变量,currentValue 当前数组成员的值

把循环遍历算法与累加器算法分离开来

一、求和

注意第一个参数是如何来的。

console.log('prev', 'cur', 'index');
var arr = [1, 2, 3, 4];
var sum = arr.reduce(function(prev, cur, index) {
    console.log(prev, cur, index);
    return prev + cur;
})
console.log(arr, sum);

console.log('prev', 'cur', 'index');
var arr = [1, 2, 3, 4];
var sum = arr.reduce(function(prev, cur, index) {
    console.log(prev, cur, index);
    return prev + cur;
}, 10)
console.log(arr, sum);
var arr = [1, 2, 3, 4];
var sum = arr.reduce(function(prev, cur, index) {
    console.log(prev, cur, index);
    return prev + cur;
})

// 等同于
var arr = [1, 2, 3, 4];
var sum = arr.reduce(function(prev, cur, index) {
    console.log(prev, cur, index);
    return prev + cur;
}, 0)

对象数组中的属性求和

var result = [
    { subject: 'math', score: 10 },
    { subject: 'chinese', score: 20 },
    { subject: 'english', score: 30 }
];

var sum = result.reduce((prev, cur) => cur.score + prev, 0);
console.log(sum) // 60

二、求数组最大值

var arr = [100, 2, 109, 4];
var max = arr.reduce(function (prev, cur) {
    return Math.max(prev,cur);
});
console.log(max);

三、统计数组中重复的元素

initialValue 是一个空对象

const initialValue = {};
var arr = ["apple","orange","apple","orange","pear","orange"]; 
function getWordCnt(){ 
  return arr.reduce(function(prev,next){ 
    prev[next] = (prev[next] + 1) || 1; 
    return prev; 
  }); 
} 
console.log(getWordCnt());//{apple: 2, orange: 3, pear: 1}

prev[next] = (prev[next] + 1) || 1; 主要是运用短路表达式的隐式转换,

参考 JavaScript 中的逻辑运算符和短路表达式

四、数组去重

initialValue 是一个空数组

var initialValue = [];
var arr = [1,2,3,4,4,1]
var newArr = arr.reduce((pre,cur)=>{
    return !pre.includes(cur) ? pre.concat(cur) : pre
},initialValue)
console.log(newArr);// [1, 2, 3, 4]```

PS: 在 ES6 中使用 Set数据结构和数组的扩展运算符(...), 参考 Set 和 Map 数据结构

// 去除数组的重复成员
[...new Set(array)]

五、链式操作

var pipe = function (value) {
  var funcStack = [];
  var oproxy = new Proxy({} , {
    get : function (pipeObject, fnName) {
      if (fnName === 'get') {
        return funcStack.reduce(function (val, fn) {
          return fn(val);
        },value);
      }
      funcStack.push(window[fnName]);
      return oproxy;
    }
  });

  return oproxy;
}

var double = n => n * 2;
var pow    = n => n * n;
var reverseInt = n => n.toString().split("").reverse().join("") | 0;

pipe(3).double.pow.reverseInt.get; // 63

这段用 数组实例方法 reduceES6 原生提供的 Proxy,可以将读取属性的操作(get),转变为执行某个函数,从而实现属性的链式操作。