文章介绍
本文很简短,主要讲解的是使用递归时会遇到的坑,以及解决的办法。并不会讲解递归是什么和它的工作原理是什么!
内容
首先,我们以经典的阶乘函数为例:
function factorial (num) {
if (num <= 1) {
return 1;
} else {
return factorial(num-1) * num;
}
}
以上代码正常使用并不会出现什么错误,但是如果有一天,我突然觉得这函数名太长了,想把它改改,改成如下:
function factorial (num) {
if (num <= 1) {
return 1;
} else {
return factorial(num-1) * num;
}
}
//注:函数指的是函数对象,而不是标识符fac、factorial
//该函数引用+1
var fac = factorial;
//该函数引用-1
factorial = null;
var n = fac(10); //报错!
因为函数的内部 return factorial(num-1) * num;
依然使用着标识符factorial
,而为了让函数的引用数-1,我们已经让factorial置为null(这是很常见的做法)。因此报错!
所以这样写一个递归函数,代码的容错性是很低的!
因为我们可以利用arguments.callee来解决这个问题:
function factorial (num) {
if (num <= 1) {
return 1;
} else {
return arguments.callee(num-1) * num;
}
}
var fac = factorial;
factorial = null;
var n = fac(10); //运行正常
但是,在严格模式下,不能使用arguments.callee
这个属性。我在另一篇文章有介绍严格模式--详解JavaScript严格模式
因此在严格模式下,我们就必须要使用到函数名来调用,并且修改函数名后,依然能正常使用。
那么我们可以利用命名函数表达式来实现
var factorial = function f(num) {
if (num <= 1) {
return 1;
} else {
return f(num-1) * num;
}
};
var fac = factorial;
factorial = null;
var n = fac(10); //运行正常
这样,我们就能随意更改函数名了!
注意:写成这样,全局作用域是访问不到f的
上面例子中,console.log(f);
将会报错!
网友评论