SOURCE

function factorial(n, total) {
  if (n === 1) return total;
  console.log(`n-1 = ${n-1}, n * total = ${n}*${total}`)
  return factorial(n - 1, n * total);
}
factorial(5, 1) // 120

/*
题目:比如数字5, 5乘到1, n*(n*1)*(n-2)...*1

注:乘号前面是“被乘数”,后面是“乘数”;乘号后面是“乘数”

 */
const demo1 = (n) =>{
    if(n===1) return 1;//这里return n也行,但是会多取一次寻值
    //另一个我自己卡住的理解, return 1 也是demo1(1)
    //即 demo1(5)*demo1(4)*demo1(3)*demo1(2)*demo1(1)
    return n*demo1(n-1) //
    //相当于demo1这个方法通过if分成了fn1和fn2
    //如果不满足if就是fn2,不仅在总算式上拼接出当前的被乘数(乘号前面),还要创建计算下一个乘数的方法demo1(n-1)这个调用
    //如果满足if,就是fn1,只需一个方法调用就行,然后可以直接给出这次调用结果来替代调用
}
console.log(demo1(5))
console.log("===")

/*
尾调用优化思路理解:
优化前 每次都用当前n去乘一个demo1(n-1)的调用
优化后 只执行一个demo2的方法调用,不在对这个方法的返回值做后续操作,但是要在入参中加入新参数的计算以及当前结果值的更新

 */
const demo2 = (n, total = 1)=>{
    console.log(`total=${total}`)
    if(n===1) return total;//如果乘到最后一位,则不更新这个total变量
    return demo2(n-1,total*n) //这里其实是 new_total = prev_total*prev_n,new_n = n-1然后每次都用demo2(new_n,new_total)
}
console.log(demo2(5))
console 命令行工具 X clear

                    
>
console