reduce 的学习方法
array.reduce(callback(prev, currentValue, index, arr), initialValue) //简写就是下面这样的 arr.reduce(callback,[initialValue]) callback (执行数组中每个值的函数,包含四个参数) 1、prev (上一次回调返回的值,或者是提供的初始值(initialValue)) 2、currentValue (数组中当前被处理的元素) 3、index (当前元素在数组中的索引) 4、array (调用 reduce 的数组) 需要注意的是 initialValue的值是任意的哈。可以是数组可以是对象。
简单使用 reduce
var arr = [1, 2, 3, 4]; var sum = arr.reduce(function(prev, cur, index, arr) { console.log(prev, cur, index); return prev + cur; }) console.log(arr, sum); //打印结果: //1 2 1 //3 3 2 //6 4 3 //[1, 2, 3, 4] 10
分析上面这个案例
这里可以看出,上面的例子index是从1开始的。 第一次的prev的值是上一次回调返回的值,或者是提供的初始值。 或者是数组的第一项的值。 因此第二次的 prev 是3=1+2(上一次回调返回的值 prev + cur) 因此第三次的 prev 是6=1+2(上一次回调返回的值 3 + 3) 我们发现数组长度是4,但是reduce函数循环3次。 说明reduce是从索引index为是从1开始循环的。
reduce 第二个参数提供初始值
var arr = [1, 2, 3, 4]; var sum = arr.reduce(function(prev, cur, index, arr) { console.log(prev, cur, index); return prev + cur; }, 10) console.log(arr, sum); //打印结果: // 10 1 0 // 11 2 1 // 13 3 2 // 16 4 3 // [1, 2, 3, 4] 20
分析第二个参数提供初始值
前端我们说了:prev (上一次回调返回的值,或者是提供的初始值(initialValue)) 因为提供了初始值,所以第一次是10, 当前值就变为了1,索引就从0开始了。 因此第一次的值是 10 1 0 第二次prev (上一次回调返回的值)11=10+1 第三次prev (上一次回调返回的值)13=13+3
数组为空,运用reduce是什么情况
var arr = []; var sum = arr.reduce(function(prev, cur, index, arr) { console.log(prev, cur, index); return prev + cur; }) console.log(arr, sum); //报错: Reduce of empty array with no initial value at Array.reduce (<anonymous>) 如果我们设置了初始值呢? var arr = []; var sum = arr.reduce(function(prev, cur, index, arr) { console.log(prev, cur, index); //这一条语句不 return prev + cur; }, 10) console.log(arr, sum); //[] 10
reduce的累加,累乘
// 累加 let sum = [1, 2, 3, 4, 5].reduce((prev, cur) => prev + cur); console.log(sum) //输出15 let sum = [1, 2, 3, 4, 5].reduce((prev,cur) => prev * cur); console.log(sum) //输出120 let sum = [1, 2, 3, 4, 5].reduce((prev, cur) => prev * cur, 10); console.log(sum) //输出1200
reduce数组对象求和
let arr = [{ money: 100, name: '苹果' }, { money: 50, name: '香蕉' }] 不使用初始值 function sum(arr) { return arr.reduce((prev, cur) => { return prev.money + cur.money }) } 使用初始值 function sum(arr) { return arr.reduce((prev, cur) => { return cur.money + prev }, 0) } console.log(sum(arr)) //输出150
reduce计算数组中每个元素出现的次数[面试经常问]
let names = ['yes', 'hello', 'hi', 'yes', 'yy']; // 第二个初始值是一个对象,因为有初始值,所以cur的值是数组的第一项[yes] let nameNum = names.reduce((pre, cur) => { // 第一次pre是一个对象,返回将这个对象返回,下一次pre又是一个对象了 if (cur in pre) { pre[cur]++ } else { pre[cur] = 1 } return pre }, {}) console.log(nameNum); //{yes: 2, hello: 1, hi: 1, yy: 1}
reduce实现数组去重[面试经常问]
let arr = [10, 20, 20, 41, 41, 1] // 这次初始值是一个数组,,因为有初始值,所以cur的值是数组的第一项10 let newArr = arr.reduce((pre, cur) => { // 如果没有,使用concat添加进去。这样就可以实现数组去重了 if (!pre.includes(cur)) { return pre.concat(cur) } else { return pre } }, []) console.log(newArr); // [10, 20, 41, 1]
reduce实现数组扁平化
let arr = [ [1, 2], [1, 2, 3], [1, [1, 3, [1, 2, 3]]] ] function flatten(arr) { return arr.reduce((pre, cur) => pre.concat(Array.isArray(cur) ? flatten(cur) : cur), []); } console.log(flatten(arr)) //[1, 2, 1, 2, 3, 1, 1, 3, 1, 2, 3]
总结:reduce有无第二个参数的区别
1=>没有提供初始值,索引是从1开始的。提供了初始值索引是从0开始的。 2=>没有提供初始值循环次数等于数组长度-1。 提供了初始值循环次数等于数组的长度; 3=>没有提供初始值第一次cur是索引为1的那个值。提供了初始值cur是索引为0的那个值 4=>没有提供初始值空数组会报错。提供了初始值空数组不会报错。[] 10