Javascript 的递归函数中的加法赋值未达到预期 运行

Addition assignment did not run as expected in Javascript's recursive functions

以下使用加法赋值的函数,当传递大于1的整数时,ans的值总是变为1

let ans = 0;
function reduce(num){
    if(num == 0){
        return 0;
    }
    ans += reduce(num-1);
    return 1;
}
reduce(5);
console.log(ans); // 1

但是当我先将递归结果保存到另一个变量时,函数运行正常(ans将更改为num-1

let ans = 0;
function reduce(num){
    if(num == 0){
        return 0;
    }
    let tmp=reduce(num-1);
    ans += tmp;
    return 1;
}
reduce(5);
console.log(ans); // 4

这是怎么发生的?这是 Javascript 的特性还是环境中的错误?

我试过类似的 C 代码,它们的行为都一样

#include<stdio.h>
int reduce(int num);
int ans;
int main(){
    ans = 0;
    reduce(5);
    printf("%d",ans); // 4
}

int reduce(int num){
    if(num == 0){
        return 0;
    }
    int tmp=reduce(num-1);
    ans += tmp;
    // ans += reduce(num-1);
    return 1;
}

环境:

发生这种情况是因为在 JavaScript 中 ans += reduce(num-1) 被评估为:

ans = ans + reduce(num-1)

而不是:

ans = reduce(num-1) + ans;

(参见 ECMAScript 规范中的 (13.15.2) Runtime semantics: evaluation)。

所以 ans 在递归调用之前被 求值 ,并且 求值 值被用作加法的操作数。

您可以通过避免具有 side-effects. A pure 递归解决方案的函数来避免此类意外行为:

function reduce(num) {
    if (num < 2) {
        return 0;
    }
    return reduce(num-1) + 1;
}
let ans = reduce(5);
console.log(ans); // 4