上次呢,自己封装了一些js里Array的语法糖,如filter, map, forEach呀,最后留了个reduce,今天就来说说这个reduce。
reduce
先看看它的用法:
// reduce要传两个参数, 一个是回调函数,一个是第一次迭代total的默认值
// 第二个参数可以不传但是,不传第二个值在迭代时,会少迭代一次,这时reduce将数组的第一位作为total第一次的值, currentValue从第二位开始
var lastTotal = arr.reduce(function (total, currentValue, currentIndex, arr) {
// 回调参数 total 第一次是reduce传的第二个值, 后面是回调的返回值
// currentValue迭代出的数组值
// currentIndex 迭代的数组索引
// arr 数组本身
console.log(total, currentValue, currentIndex, arr);
//每次迭代打印值为:
// {name: 'reduce'} 1 0 (3) [1, 2, 3]
//1 2 1 (3) [1, 2, 3]
//2 3 2 (3) [1, 2, 3]
return currentValue;
}, {name: 'reduce'})
console.log(lastTotal) // 3 reduce的返回值是最后一次迭代的total
之前在工作中几乎忽略了这个方法,很少用到,其实它在有些场景下还是很好用的,例子:
// 有一个cookie的字符串解析成对象的需求
var cookieStr = "cookie1=DBBDAA44573FEFADF1649F552ACDEACB; cookie2=sadas46da4s6d8; cookie3=8weqr98qw7e98_asda; token=as4d654as65d";
function cookieAnalysis (str) {
// 先用;把字符串拆分成数组
var arr = str.split(';');
// 然后reduce出场了, reduce的第二个值传一个空对象用于保存cookie对象
var cookieObj = arr.reduce(function (total, currentValue) {
// 把迭代出的每一项再以等号拆分
var tempArr = currentValue.split('=');
// 把拆分的数组第一位作为对象属性名,第二位作为属性值
total[tempArr[0]] = tempArr[1];
// 再把对象返回作为下一次的total
return total;
}, {});
// 最后把迭代完的 对象返回出去
return cookieObj;
}
console.log(cookieAnalysis(cookieStr));
//{cookie1: "DBBDAA44573FEFADF1649F552ACDEACB", " cookie2": "sadas46da4s6d8", " cookie3": "8weqr98qw7e98_asda", " token": "as4d654as65d"}
当然这用其他的方法也能实现,但是用reduce更方便一些。好下面来自己封装一下reduce:
Array.prototype.myReduce = function (callback, initialValue) {
// 数组这些方法都来不开for循环
for (var i = 0; i < this.length; i ++) {
if (i === 0) {
// 先判断一下 initialValue有没有传 这里用undefined来判断了 要是传的undefined就无法搞了
// 没想出其他的解决方案
if(initialValue === undefined) {
// 直接i ++ 把第一位作为initialValue 传进去,下一轮
// 并用initialValue接收callback返回值作为下一次循环的initialValue
initialValue = callback(this[i], this[i + 1], i + 1, this);
i ++;
continue;
}
// 传了initialValue就一切正常喽
initialValue = callback(initialValue, this[i], i, this);
} else {
initialValue = callback(initialValue, this[i], i, this);
}
}
// 循环完成把最后一次的initialValue丢出去
return initialValue;
}
搞定实验一下:
var arr1 = [1, 2, 3]
arr1.myReduce(function(total, currentValue, currentIndex, arr){
console.log(total, currentValue, currentIndex, arr);
}, {name: 'myReduce'})
貌似没有问题,嘻嘻要是哪位大神有更好的实现方式,活着看出了我代码中的bug,欢迎拍砖额,闪人。