最近做一个关于数组迭代方法reduce的扩展的题目,记录一下。第一次写简书,感觉棒棒哒!如有错误,欢迎指点斧正。
1、题目如下:
设计一个对数组的特殊reduce函数。它的参数表为:
- 数组
- 回调函数
- 初始值(可选)
和普通的reduce的区别是回调函数callback接受n个参数,参数列表如下:
- 上次计算的结果
- 数组连续的k个元素(k<=m)
例如:
var list = [1, 2, 3, ..., m];
var iter_a = function (sum, a, b) {
return sum + a * b;
};
var iter_b = function (sum, a, b, c, d) {
return sum + a / b / c / d;
};
reduce(list, iter_a, 17);
reduce(list, iter_b, 11);
最后得到的结果应该是:
iter_a: 17 + 1 * 2 + 2 * 3 + 3 * 4 + ... + (m - 1) * m
iter_b: 11 + 1 / 2 / 3 / 4 + 2 / 3 / 4 / 5 + ... + (m - 3) / (m - 2) / (m - 1) / m
2、解题过程
先去MDN看了下reduce,在polyfill部分找到解题思路。其中给出了普通reduce的实现方案。参考源码,再依据题目的具体需求进行修改便可得出我们所想要的扩展的reduce。
(1)和ECMAScript 5中reduce最大的区别是,这边传入的callback函数的参数是不定的
在不超出数组最大范围的情况下,callback函数参数个数可以是2~m+1个,所以我们必须要在reduce内部去获得callback的参数的个数
var count = callback.length;
(2)每次迭代的数组中k个连续元素
我们需要对迭代循环和callback参数进行修改
for(;k<len-count+2;k++){
args.push(value);//第一个参数的回调值
for(var i=0;i<count-1;i++){
args.push(array[k+i]);
}
if(k in array){
value = callback.apply(this,args);//通过apply将参数数组装入callback
}
args.length = 0;//参数数组清空,来存放下次迭代所需参数
}
3、reduce扩展代码
function Reduce(array,callback,initalValue){
var len = array.length,
k = 0,
value = 0;
if(arguments.length == 3){
value = arguments[2];
}
else{
while (k < len && !(k in array)) {
k++;
}
if (k >= len) {
throw new TypeError('Reduce of empty array with no initial value');
}
value = array[k++];
}
var count = callback.length;
var args = [];
for(;k<len-count+2;k++){
args.push(value);//第一个参数的回调值
for(var i=0;i<count-1;i++){
args.push(array[k+i]);
}
if(k in array){
value = callback.apply(this,args);//通过apply将参数数组装入callback
}
args.length = 0;//参数数组清空,来存放下次迭代所需参数
}
return value;
}
4、参考资料
(1)reduce in MDN
(2)《Javascript高级程序设计(第3版)》