Para las siguientes funciones que usan asignación de suma, el valor de ans siempre se cambia a 1 cuando se pasa un número entero mayor que 1
let ans = 0; function reduce(num){ if(num == 0){ return 0; } ans += reduce(num-1); return 1; } reduce(5); console.log(ans); // 1 Pero cuando primero guardo el resultado recursivo en otra variable, la función funciona bien ( ans se cambiará a 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¿Como sucedió esto? ¿Es esta una característica de Javascript o un error en el entorno?
He probado códigos C similares y todos se comportan igual
#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; }Ambiente:
Esto sucede porque en JavaScript ans += reduce(num-1) se evalúa como:
ans = ans + reduce(num-1)y no como:
ans = reduce(num-1) + ans;(Consulte (13.15.2) Semántica de tiempo de ejecución: evaluación en las especificaciones de ECMAScript).
Entonces, ans se evalúa antes de que se realice la llamada recursiva, y es ese valor evaluado el que se usa como operando de la suma.
Puede evitar este tipo de comportamiento inesperado evitando las funciones con efectos secundarios . Una solución recursiva pura sería:
function reduce(num) { if (num < 2) { return 0; } return reduce(num-1) + 1; } let ans = reduce(5); console.log(ans); // 4