散装JS - 图解callee经典案例阶乘10!

35 阅读2分钟

在js函数学习中,Argument类数组对象具有的callee属性是实现函数递归的一个常见用法,尤其使用callee实现10!阶乘,是该语句的经典案例。

            if (num == 1) {
                return 1;
            } else {
                return num * arguments.callee(num - 1);
            }
        }
        alert(sum(10));

其中,callee代表函数本身,使用callee的优点在于避免后续函数名修改影响函数内部。也就是说,使用callee修改函数名,对函数内部执行与函数本身有关的递归结构时,不需要层层修改函数名(但是也可以使用查找修改哈)。
在这个案例中,callee的作用在于补充阶乘数列中从10开始之后的每一个(n-1)的乘数,具体来说,就是在return时套入下一个sum(n-1)。 内部运算方法就是:

  • 10* arguments.callee(9);
  • 10*( 9* arguments.callee(8))
  • 10*( 9*( 8* arguments.callee(7)))
  • 10*( 9*( 8*( 7* arguments.callee(6))))
  • 10*( 9*( 8*( 7*( 6* arguments.callee(5)))))
  • 10*( 9*( 8*( 7*( 6*( 5* arguments.callee(4))))))
  • 10*( 9*( 8*( 7*( 6*( 5*( 4* arguments.callee(3)))))))
  • 10*( 9*( 8*( 7*( 6*( 5*( 4*( 3* arguments.callee(2))))))))
  • 10*( 9*( 8*( 7*( 6*( 5*( 4*( 3*( 2* arguments.callee(1)))))))))

因此最后一个返回return 1并不是return给了sum,而是return给了上一层的sum(2),然后sum(2)再return给sum(3)...直至返回给sum(10).
如下图所示,先看黑线,函数先通过每一个fun(n-1)套娃递进,直到最里层函数获得值(即fun(1)return给的1)。然后再看红线,回归最上层的fun(10)获得最终值。这一深入再出来的过程形成递归结构。

微信截图_20230404151000.png

引用一个清楚一点的例子理解递归结构:

目前我找到的对递归最恰当的比喻,就是查词典。

我们使用的词典,本身就是递归,为了解释一个词,需要使用更多的词。

当你查一个词,发现这个词的解释中某个词仍然不懂,于是你开始查这第二个词,可惜,第二个词里仍然有不懂的词,于是查第三个词,这样查下去,直到有一个词的解释是你完全能看懂的,那么递归走到了尽头,然后你开始后退,逐个明白之前查过的每一个词,最终,你明白了最开始那个词的意思。。。

作者:李鹏
链接:www.zhihu.com/question/20…
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

这样可以理解callee的作用了吧~~