递归函数是在一个函数通过名字调用自身的情况下构成的,在中曾拿来举过例子:
//阶乘函数function factorial(num){ if(num <= 1){ return 1; }else{ return num * factorial(num - 1); }}console.log(factorial(4));//24
这种写法在函数有名字,而且名字以后也不会变的情况下是没有问题的。但是函数的执行与函数名factorial
紧紧耦合在了一起,当函数名发生变化时,调用就出现了问题:
var trueFactorial = factorial;factorial = null;console.log(trueFactorial(4));//Uncaught TypeError: factorial is not a function
使用arguments.callee
可以达到解耦的目的:
function factorial(num){ if(num <= 1){ return 1; }else{ return num * arguments.callee(num - 1); }}var trueFactorial = factorial;factorial = null;console.log(trueFactorial(4));// 24
如代码所示,无论将来函数名如何变化,始终都能保证正确的执行结果。
其中还说到,在严格模式下JavaScript是不支持arguments
的,那么此时要实现一个松散耦合的递归函数该怎么实现呢?也很简单,可以结合使用函数表达式与函数声明的方式来定义递归函数:
var factorial = function f(num){ if(num <= 1){ return num; }else{ return num * f(num - 1); }}console.log(factorial(5));// 120console.log(f(5));// Uncaught ReferenceError: f is not defined
这样声明的函数,函数名是f
但是在作用域中存在的引用为factorial
,在f
的内部可以访问到f
,利用这个特点就做到了函数的调用与函数名的完全解耦合,无论将来调用方式如何变化,都不会影响执行结果:
var trueFactorial = factorial;factorial = null;console.log(trueFactorial(4));// 24