日常的学习笔记,包括 ES6、Promise、Node.js、Webpack、http 原理、Vue全家桶,后续可能还会继续更新 Typescript、Vue3 和 常见的面试题 等等。
reduce
let r = [1, 2, 3, 4, 5].reduce((total, num) => {
return total + num
})
console.log(r);
reduce()
方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。
reduce()
可以作为一个高阶函数,用于函数的 compose。
(注:reduce()
对于空数组是不会执行回调函数的。)
简单来说,reduce
中会接受一个函数,函数的第一次循环,会将数组的前两项传入,并执行相应的计算,并将结果返回。往后的每一次循环,都会将上一次循环的结果传递到第一个参数中。
initialValue
initialValue , reduce()
的第二个参数,表示传递给函数的 初始值 。
我们可以用它来计算购物车的总价格
let r = [{price: 100, count: 1}, {price: 200, count: 2}, {price: 300, count: 3}].reduce((total, num) => {
return total + num.price * num.count
}, 0)
console.log(r); // 1400
这样我们整个数组默认的第一项就变成了 0,对于处理这种非数字数组非常好用。
currentIndex
currentIndex , reduce()
函数的第三个参数,表示当前 元素的索引。
我们可以用它来将多个数据合并成一个数据。
let keys = ['name', 'age'];
let values = ['mxs', 18];
let obj = keys.reduce((memo, cur, index) => {
memo[cur] = values[index]
return memo
}, {});
console.log(obj); // {name: 'mxs', age: 18}
模拟compose函数逻辑
compose
函数,函数调用扁平化。一个函数的运行结果当作实参传给下一个函数的这种操作,使复杂函数调用看起来更清晰。
假设我们目前需要实现这样一个功能
有两个 String
字符串,将其 拼接 并 转换成大写 ,最后再 添加特殊字符并展示。
我们可能会这样解决这个问题。
let str1 = 'mxs'
let str2 = 'nb'
function sum(a, b) {
return a + b
}
function toUpper(str) {
return str.toUpperCase()
}
function add(str) {
return '***' + str + '***'
}
console.log(add(toUpper(sum(str1, str2)))) // ***MXSNB***
我们只模拟了三种功能,整个代码就已经很繁琐了。
我们为了简化这种繁琐的代码,可以利用 compose函数 对其进行处理。
function compose(...fns) {
return function (...args) {
let fn = fns.shift();
return fns.reduce((a, b) => {
return b(a)
}, fn(...args))
}
}
let r = compose(sum, toUpper, add)(str1, str2)
console.log(r); // ***MXSNB***
我们用一个名为 compose函数 的方法进行 闭包封装 ,这样会使输出代码看起来更整洁,逻辑更清晰。
可以利用箭头函数简化 compose函数 代码
let compose = (...fns) => (...args) => {
let fn = fns.shift();
return fns.reduce((a, b) => b(a), fn(...args))
}
同时,我们还可以在实现思路上进行简化。
function compose(...fns) {
return fns.reduceRight((a, b) => {
return (...args) => {
return a(b(...args))
}
})
}
这种实现方式非常难理解,但是也很好解释通,私下可以花点时间看一下。
然后我们再对其写法进行简化,最终就会变成如下代码。
let compose = (...fns) => fns.reduceRight((a, b) => (...args) => a(b(...args)))
最终就成了一行代码。
这行代码也被应用在 redux源码 中。
手写实现reduce
Array.prototype.reduce = function (callBack, prev) {
for (let i = 0; i < this.length; i++) {
if (prev == undefined) {
prev = callBack(this[i], this[i + 1], i + 1, this);
i++;
} else {
prev = callBack(prev, this[i], i, this)
}
}
return prev
}
let r = [1, 2, 3].reduce((a, b, index, current) => a + b)
let r2 = [1, 2, 3].reduce((a, b, index, current) => a + b, 100)
console.log(r); // 6
console.log(r2); // 106
实现思路大体就是,利用将传入数组进行循环,执行函数并输出其结果。 假如有第二个参数,就对第二个参数进行处理。 若没有,则直接进行输出处理即可。
map
循环每一项,并对数组中的每一项进行处理,随后将处理后的结果以新数组的方式返回,不会改变原数组。
let arr = [1, 2, 3]
let newArr = arr.map(item => item * 2);
console.log(newArr, arr) // [ 2, 4, 6 ] [ 1, 2, 3 ]
filter
过滤数组,将结果为 false
的项过滤掉,并将结果返回。
let arr = [1, 2, 3]
let newArr = arr.filter(item => item != 2);
console.log(newArr, arr) // [ 1, 3 ] [ 1, 2, 3 ]
some
查看当前数组中是否存在与输出条件一致的结果,如果有则输出 true
,反之为 false
。 此方法与 every 方法相反
let arr = [1, 2, 3]
let newArr = arr.some(item => item == 2);
console.log(newArr) // true
every
查看当前数组中是否存在与输出条件不一致的结果,如果有则输出 true
,反之为 false
。 此方法与 some 方法相反
let arr = [1, 2, 3]
let newArr = arr.every(item => item == 2);
console.log(newArr) // false
find
查找数组中与函数条件一致的那一项结果,并将其返回。如果没找到,则返回 undefined
let arr = [1, 2, 3]
let newArr = arr.find(item => item == 2);
console.log(newArr) // 2
includes
查找数组中是否包含函数条件的那一项结果,有则输出 true
,没有输出 false
let r = [1, 2, 3].includes(2)
console.log(r); // true
本篇文章由莫小尚创作,文章中如有任何问题和纰漏,欢迎您的指正与交流。
您也可以关注我的 个人站点、博客园 和 掘金,我会在文章产出后同步上传到这些平台上。
最后感谢您的支持!