JavaScript递归函数总结(含面试题)

什么是递归函数?

一个通过函数名调用自身的函数

递归函数的注意点

  • 一定要有结束条件,否则会导致死循环
  • 能用递归函数实现的需求,就一定可以用循环调用函数来解决,只是代码简洁与性能不同而已

递归函数的应用场景

1.求阶乘: 求n的阶乘
  • 循环写法
        function getMul(n){
            var data = 1;
            for(var i = 1;i<=n;i++){
                data *= i
            }
            return data;
        }
        console.log(getMul(4));//24
  • 递归写法
    a.推理版:中间省略
        function getMul(n){
            if(n == 1){
                return 1;
            }else if(n == 2){
                return 2 * getMul(1);
            }else if(n == 3){
                return 3 * getMul(2)
            }
            //*****
            else if(n == n){
                return n * getMul(n-1);
            };
        };
        console.log(getMul(4));//24

b.精简版:三元表达式

        function getMul(n){
            return n == 1 ? 1 : n * getMul(n-1);
        };
        console.log(getMul(4));//24
2.求1-n的累加和
  • 循环写法
        function getSum(n){
            var data = 0;
            for(var i = 1;i<=n;i++){
                data += i;
            }
            return  data;
        };
        console.log(getSum(4));//10
  • 递归写法
    a.推理版:中间省略
        function getSum(n){
            if(n == 1){
                return 1;
            }else if(n == 2){
                return n + getSum(1);
            }else if(n == 3){
                return n + getSum(2);
            }else if(n == 4){
                return n + getSum(3);
            }
           // ………………
            else if(n == n){
                return n + getSum(n-1)
            }
        };
        console.log(getSum(4));//10

b.精简版:三元表达式

        function getSum(n){
            return n==1 ? 1:n + getSum(n-1);
        };
        console.log(getSum(4));//10
3.求斐波拉契数列
  • 斐波拉契数列: 前面两个数字是固定的1,从第三个数字开始,每一个数字都是前面两个数字的和
循环数组写法(性能好)

思路:1.每次计算都是前两个数字之和,其他的数据没有什么用,所以每次只计算两个
arr[n]=arr[n-1]+arr[n-2]

灵魂画手

        function getData(n) {
            var arr = [1, 1];
            for (var i = 2; i < n; i++) {
                arr[i] = arr[i - 1] + arr[i - 2];
            };
            console.log(arr);//[1,1,2,3,5,8,13,21,34,55]
            return arr[arr.length - 1];
        };
        console.log(getData(10)); //10
递归写法

a.推理版:中间省略


        function getData(n) {
            if(n == 1 || n == 2){
                return 1;
            }else if(n == 3){
                return getData(2) + getData(1);
            }else if(n == 4){
                return getData(3)+getData(2);
            }else if(n == 5){
                return getData(4) + getData(3)
            }
           // …………
            else if(n == n){
                return getData(n-1) + getData(n-2)
            };
        };
        console.log(getData(10)); //10

b.精简版:三元表达式

        function getData(n) {
            return (n == 1 || n == 2)?1 : getData(n-1) + getData(n-2);
        };
        console.log(getData(10)); //10
4.遍历DOM树:获取所有的后代元素

a.需求:获得div中所有的后代元素
b.思路:获取father的子代元素。 继续检查该元素是否有子代元素,
如果有则继续循环获取子代,依次类推,形成递归调用

            <div id="father">
        <div>
            <span>1</span>>
        </div>
        <p>
            <span>11</span>
            <span>22</span>
        </p>
        <a href="#">boJack</a>
        <div>
            <div>
                <b>Todd</b>
            </div>
        </div>
    </div>
    <script>
        var father = document.getElementById('father');
        var list = []; //声明空数组存储所有的后代元素
        function getHouDai(ele) {
            for (var i = 0; i < ele.children.length; i++) {
                list.push(ele.children[i]);
                getHouDai(ele.children[i]);
            };
        };
        getHouDai(father);
        console.log(list);//[span,p,span,span,a,div,div,b]

// 遍历整颗DOM树
        getHouDai(document);
        console.log(list);
    </script>

经典面试题以及推荐用法

a.写出该题打印的值

        var res = (function(n){ return n==1?1:n*arguments.callee(n-1)})(6);
        console.log('res' + res);//res720

考察的知识点:argument.callee

  • argument.callee是一个指向正在执行的函数的指针,使用它来代替函数名,可以确保无论怎样调用函数都不会出问题
        function res(n) {
            return n ==1 ? 1 : n * res(n - 1);
        };
        var  data = res;
        res = null;
        console.log(data(4));
        //res is not a function

由于res变量设置为Null,结果指向原始函数的引用只剩下一个,res已经不是函数,而调用data()会执行res,所以会报错;而使用arguments.callee可以解决这个问题

        function res(n) {
            return n ==1 ? 1 : n * arguments.callee(n - 1);
        };
        var  data = res;
        res = null;
        console.log(data(4));//24

推荐用法

  • 严格模式:使用arguments.callee会报错,不过我们可以通过命名函数表达式来达到相同的效果
    以下代码创建了一个f()的命名函数表达式,赋值给res变量,即使把函数赋值给另一个变量,函数的名字依然有效,递归能正常完成,这种方式在严格模式和非严格模式都能运行
        var res=(function f(n) {
            return n ==1 ? 1 : n * f(n - 1);
        });
        console.log(res(4));//24
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342