You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义_reduce函数调用后原数组未修改?预期结果不符求解

为什么原数组未被修改?

先看你提供的代码和运行结果:

相关代码

遍历函数_each

function _each(list, iter){
    for(var i=0; i<list.length; i++){
        iter(list[i]);
    }
}

类数组兼容的_rest函数

var slice = Array.prototype.slice;
function _rest(list, num){
    return slice.call(list, num || 1);
}

自定义_reduce函数

function _reduce(list, iter, memo){
    if(arguments.length == 2){
        memo = list[0];
        list = _rest(list);
    }
    _each(list, function(val){
        memo = iter(val, memo);
    })
    return memo;
}

调用代码

var arr = [1, 2, 3, 4];

console.log(_reduce(arr, function(a, b){return a + b}));
console.log(arr);

实际输出

10
(4) [1, 2, 3, 4]

你预期原数组会变成[2,3,4]但没实现,核心原因有两点:

核心原因

  1. _rest返回的是新数组而非修改原数组
    slice.call(list, num || 1)调用的是数组的slice方法,这个方法的特性是不修改原数组,而是返回一个包含原数组从指定索引开始的所有元素的新数组。所以_rest并没有动过原数组的内容。

  2. 函数内部的list变量是局部引用
    当你把arr传入_reduce时,函数内部的list变量拿到的是原数组引用的副本。执行list = _rest(list)只是把这个局部变量的指向换成了_rest返回的新数组,完全不会影响外部的arr变量——它依然指向最初的那个数组。

说白了,你只是在函数内部换了个局部变量的指向,根本没碰原数组的内容,所以原数组自然不会有变化。

如果非要修改原数组(不推荐,会产生副作用),可以直接操作原数组,比如用shift()方法:

function _reduce(list, iter, memo){
    if(arguments.length == 2){
        memo = list[0];
        list.shift(); // 直接移除原数组的第一个元素
    }
    _each(list, function(val){
        memo = iter(val, memo);
    })
    return memo;
}

但实际开发中,更推荐保持原数组不变的写法,也就是你最初的实现,这样的代码更符合函数式编程的无副作用原则,避免意外的bug。

内容的提问来源于stack exchange,提问作者이규빈

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 13:25:03