JavaScript使用递归的最佳方案

文章介绍

本文很简短,主要讲解的是使用递归时会遇到的坑,以及解决的办法。并不会讲解递归是什么和它的工作原理是什么!

内容

首先,我们以经典的阶乘函数为例:

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); 将会报错!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 本文档内容参考 《JavaScript 闯关记》之函数 函数是一段代码,它只定义一次,但可以被执行或调用任意次。在...
    穿越人海遇见你阅读 4,599评论 0 1
  • 函数参数的默认值 基本用法 在ES6之前,不能直接为函数的参数指定默认值,只能采用变通的方法。 上面代码检查函数l...
    呼呼哥阅读 8,917评论 0 1
  • 递归思想 递归函数是在一个函数通过名字调用自身的情况下构成的,如下所示。 function factorial(n...
    前端精髓阅读 1,267评论 0 1
  • 一 人无千日好,花无百日红。人在职场,总是会遇到一些委屈的事情。有时是来自老板的不理解,有时是被利益相关同事的故意...
    三米河阅读 4,803评论 0 3
  • 今天跟王小垚讨论关于初识的事儿!! 王小垚爱逗人,那时候不知道他说的话真真假假,开始有好感的时候互相试探对方的感觉...
    两王的日常阅读 1,618评论 0 0