本文介绍JavaScript中递归函数的基本用法,以10以内阶乘为例展示经典实现。重点分析当函数名被重新赋值或置空时,原函数引用失效导致的错误。通过讲解arguments.callee属性,演示如何安全地让函数调用自身,确保在函数名改变后仍能正确执行递归逻辑。
JavaScript递归函数基础与阶乘示例
接下来我们通过一个计算10以内阶乘的实例来演示递归函数的具体应用。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>js中递归函数的使用</title> </head> <body> </body> </html> [Ctrl+A 全选 注:引入外部Js需再刷新一下页面才能执行]
关于递归函数的基本调用方式,介绍至此。
在JavaScript中,当递归函数调用自身时,存在一种确保其正常运行的安全机制。
该知识点源自《JavaScript高级程序设计》一书。
这里展示一个标准的阶乘递归函数示例。
代码实现如下:
function fact(num){
if (num<=1){
return 1;
}else{
return num*fact(num-1);
}
} 递归函数调用中的引用失效问题
以下代码片段可能会导致运行错误:
var anotherFact = fact;
fact = null;
alert(antherFact(4)); //出错
因为此时变量fact已不再指向函数,而是被赋值为null,所以调用会失败。
使用arguments.callee实现安全递归
使用arguments.callee属性可以解决这一问题,该属性指向当前正在执行的函数。
改进后的函数定义如下:
代码修改如下:
function fact(num){
if (num<=1){
return 1;
}else{
return num*arguments.callee(num-1); //此处更改了。
}
}
var anotherFact = fact;
fact = null;
alert(antherFact(4)); //结果为24. JS普通递归的改进
递归函数是指在一个函数体内通过函数名调用自身的结构,示例如下:
代码示例:
function factorial(num)
{
if(num<=1)
{
return 1;
}
else
{
return num * factorial(num-1);
}
} 这看起来是一个经典的阶乘函数,但下述代码可能导致其出现异常。
var anotherFactorial = factorial;
anotherFactorial(4); //输出 24
factorial = null;
anotherFactorial (4); //TypeError: Property 'factorial' of object [object Window] is not a function chrome 下测试
原因在于,函数名实际上是指向函数的一个指针。当我们定义anotherFactorial时,它同样指向该函数对象,因此调用anotherFactorial(4)能成功输出24。
然而,当执行factorial = null后,指向原函数的引用只剩下anotherFactorial。此时若再次调用anotherFactorial(4),由于函数内部仍尝试调用factorial,而factorial已为null,从而抛出错误。
此时可以使用arguments.callee来替代函数定义中的具体函数名,
函数的定义调整为:
代码修改如下:
function factorial(num)
{
if(num<=1)
{
return 1;
}
else
{
return num * arguments.callee(num-1);
}
} 再次使用上述4行测试代码,最后一行测试代码现在也能成功输出24。
--------------------------------------
上述内容摘自《JavaScript高级程序设计》第2版 144页 7.1节