手写代码实现reduce方法

写在开头

自己手写代码实现一个方法,需要先了解原方法的实现原理:这是开发文档地址
reduce 语法arr.reduce(callback[accumulator, currentValue, currentIndex, array], initialValue)
参数解析:
callback
必需。用于执行每个数组元素的函数。函数参数:可加入四个参数:
accumulator
是上一次计算后所回传的累加数值。
currentValue
遍历数组所在当前元素。
currentIndex(可选)
如果传initialValue,则由索引0之元素开始,若无则自索引1之元素开始。
array(可选)
当前元素所属的数组
initialValue(可选)
传递给函数的初始值

举例了解大概流程:

[1,2,3].reduce((a,b) => a+b,0)
[1, 2, 3] // 取出 1 + 2 ,填回 3
[3, 3] // 取出 3 + 3 ,填回 6
[6] // 最终结果为 6

方法1:根据上面的逻辑简单实现:


        const fn = function (totalVal, curVal, i, arr) {
            return totalVal + curVal
        };
        Array.prototype.myReduce = function fakeReduce(fn, base) {
            if (typeof fn !== 'function') {
                throw TypeError(fn + '  is not a function')
            }
            // let arr = base ? this.unshift(base) : this;// 首进,返回新数组的长度,影响原数组 故不能这么写
            let initialArr = this;
            let arr = initialArr.concat(); //得到副本

            if (base !== undefined) arr.unshift(base); // 当存在归并基础值的参数时,将其从数组首部推入
            let index = 0;
            if (arr.length == 0) {
                throw TypeError("Array can not be empty");
            }
            if (arr.length == 1) {
                return arr[0];
            }
            while (arr.length > 2) {
                index = initialArr.length - arr.length + 1;//有传递初始值,当前元素使用arr[0],否则使用arr[1],
                let newValue = fn.call(null, arr[0], arr[1], index, initialArr);
                arr.splice(0, 2, newValue);
            }
            //此时数组剩下最后两个元素,返回结果即可
            index += 1;
            let result = fn.call(null, arr[0], arr[1], index, initialArr);
            return result;
        };
        let arr = [2,22,33];
        console.log(arr.reduce(fn, 0));
        console.log("====my:====")
        console.log(arr.myReduce(fn, 0));
        

方法2:实现递归实现:


        const fn = function (totalVal, curVal, i, arr) {
            return totalVal + curVal
        };
        const reduceHelper = (fn, acc, idx, array) => {
            if (array.length === 0) return acc
            const [head, ...tail] = array
            idx++
            return reduceHelper(fn, fn(acc, head, idx, array), idx, tail)
        }

        Array.prototype.myReduce = function (cb, initialValue) {
            if (typeof fn !== 'function') {
                throw TypeError(fn + ' is not a function')
            }
            if (this.length === 0 && initialValue === undefined) {
                throw TypeError('Reduce of empty array with no initial value')
            }
            const array = this
            const [head, ...tail] = array
            const startIndex = initialValue === undefined ? 0 : 1

            return initialValue === undefined ? reduceHelper(cb, head, startIndex, tail) : reduceHelper(cb, initialValue, startIndex, array)
        }
        let arr = [2,22,33];
        console.log(arr.reduce(fn, 0));
        console.log("====my:====")
        console.log(arr.myReduce(fn, 0));

方法3:重构非递归实现:


        const fn = function (totalVal, curVal, i, arr) {
            return totalVal + curVal
        };
        Array.prototype.myReduce = function (fn, initTotalVal) {
            if (typeof fn !== 'function') {
                throw TypeError(fn + ' is not a function')
            }
            if (this.length === 0 && initTotalVal === undefined) {
                throw TypeError('Reduce of empty array with no initial value')
            }
            const array = this;
            let index = initTotalVal === undefined ? 1 : 0;
            let acc = initTotalVal === undefined ? array[0] : initTotalVal;
            for (let i = index; i < array.length; i++) {
                acc = fn(acc, array[i], index, array)
            }
            return acc
        }
        let arr = [];
        console.log(arr.reduce(fn, false));
        console.log("====my:====")
        console.log(arr.myReduce(fn, false));

结语

参考文章地址

你可能感兴趣的:(随笔记,javascript)