【问题标题】:Javascript reduce gotcha - skips first iteration?Javascript减少陷阱 - 跳过第一次迭代?
【发布时间】:2019-02-14 03:41:43
【问题描述】:

为什么javascript的reduce实现第一次迭代会跳过执行?

[1,2,3].reduce((acc, val) => {
    console.log('acc',acc);
    console.log('val',val)
    return acc + val;
});
// acc 1
// val 2
// acc 3
// val 3
// 6

我注意到第一个语句执行从未运行(在这种情况下,我预计会有 6 个控制台日志,每个元素 2 个)。当我尝试在每次迭代中使用 reduce 执行具有副作用的函数时,这是非常出乎意料的行为。

在我使用过的其他语言中,传递的列表的每次迭代都会执行。有其他例子吗?

为什么会出现这种情况,为什么javascript的原生Array reduce的实现会这样呢?

========================== 编辑1/解决方案================== ======
为了确保它通过第一次迭代,给它一个初始值(这里的第二个参数/在这种情况下为 0)

[1,2,3].reduce((acc, val) => { console.log('acc',acc); console.log('val',val) return acc + val; }, 0);

【问题讨论】:

    标签: javascript arrays functional-programming reduce


    【解决方案1】:

    这是因为在每次迭代中,第一个值都被视为return 值(或累加器)。

    直接来自here,可以看到

    累加器累加回调的返回值;它是 上次调用时返回的累积值 回调或初始值,如果提供(见下文)。


    如果我们查看源代码here,我们可以看到它是如何实现的:

    Array.prototype.myReduce = function(callback, initialVal) {
        var accumulator = (initialVal === undefined) ? undefined : initialVal;
        for (var i = 0; i < this.length; i++) {
            if (accumulator !== undefined)
                accumulator = callback.call(undefined, accumulator, this[i], i, this);
            else
                accumulator = this[i];
        }
        return accumulator;
    };
    

    else结构中,我们可以看到如果值为undefined,我们将其设置为数组中的i-th子索引;其中,对于第一次迭代,是第一次。之后,它成为后续迭代的回调(返回)值。

    如果需要,您可以回溯并检查输出。

    【讨论】:

    • 啊,是的,我现在明白了。如果我不希望它跳过第一次执行,则必须传入一个 initialValue。谢谢!
    • 我是来问这个问题的。不过,我不完全理解这里发生了什么。我应该如何传递一个 initialVal 以便在返回时不会跳过索引 0?
    • 传入 0(在我的情况下)或任何你想要的默认累加器
    猜你喜欢
    • 2013-10-03
    • 2011-08-08
    • 2021-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-07
    • 2023-03-15
    • 1970-01-01
    相关资源
    最近更新 更多