JS 遞歸函數(shù)

什么是遞歸函數(shù)?

一個(gè)通過函數(shù)名調(diào)用自身的函數(shù)

遞歸函數(shù)的注意點(diǎn)

  • 一定要有結(jié)束條件,否則會(huì)導(dǎo)致死循環(huán)
  • 能用遞歸函數(shù)實(shí)現(xiàn)的需求,就一定可以用循環(huán)調(diào)用函數(shù)來解決,只是代碼簡潔與性能不同而已

遞歸函數(shù)的應(yīng)用場景

1.求階乘: 求n的階乘
  • 循環(huá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.精簡版:三元表達(dá)式

        function getMul(n){
            return n == 1 ? 1 : n * getMul(n-1);
        };
        console.log(getMul(4));//24

2.求1-n的累加和
  • 循環(huá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.精簡版:三元表達(dá)式

        function getSum(n){
            return n==1 ? 1:n + getSum(n-1);
        };
        console.log(getSum(4));//10

3.求斐波拉契數(shù)列
  • 斐波拉契數(shù)列: 前面兩個(gè)數(shù)字是固定的1,從第三個(gè)數(shù)字開始,每一個(gè)數(shù)字都是前面兩個(gè)數(shù)字的和
循環(huán)數(shù)組寫法(性能好)

思路:1.每次計(jì)算都是前兩個(gè)數(shù)字之和,其他的數(shù)據(jù)沒有什么用,所以每次只計(jì)算兩個(gè)
arr[n]=arr[n-1]+arr[n-2]

image
        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.精簡版:三元表達(dá)式

        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的子代元素凫佛。 繼續(xù)檢查該元素是否有子代元素,
如果有則繼續(xù)循環(huán)獲取子代孕惜,依次類推愧薛,形成遞歸調(diào)用

            <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 = []; //聲明空數(shù)組存儲(chǔ)所有的后代元素
        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>

經(jīng)典面試題以及推薦用法

a.寫出該題打印的值

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

考察的知識(shí)點(diǎn):argument.callee

  • argument.callee是一個(gè)指向正在執(zhí)行的函數(shù)的指針,使用它來代替函數(shù)名,可以確保無論怎樣調(diào)用函數(shù)都不會(huì)出問題
        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變量設(shè)置為Null,結(jié)果指向原始函數(shù)的引用只剩下一個(gè),res已經(jīng)不是函數(shù),而調(diào)用data()會(huì)執(zhí)行res,所以會(huì)報(bào)錯(cuò);而使用arguments.callee可以解決這個(gè)問題

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

推薦用法

  • 嚴(yán)格模式:使用arguments.callee會(huì)報(bào)錯(cuò),不過我們可以通過命名函數(shù)表達(dá)式來達(dá)到相同的效果
    以下代碼創(chuàng)建了一個(gè)f()的命名函數(shù)表達(dá)式,賦值給res變量,即使把函數(shù)賦值給另一個(gè)變量,函數(shù)的名字依然有效,遞歸能正常完成,這種方式在嚴(yán)格模式和非嚴(yán)格模式都能運(yùn)行
        var res=(function f(n) {
            return n ==1 ? 1 : n * f(n - 1);
        });
        console.log(res(4));//24

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市诊赊,隨后出現(xiàn)的幾起案子厚满,更是在濱河造成了極大的恐慌,老刑警劉巖碧磅,帶你破解...
    沈念sama閱讀 206,482評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異遵馆,居然都是意外死亡鲸郊,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門货邓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來秆撮,“玉大人,你說我怎么就攤上這事换况≈氨妫” “怎么了?”我有些...
    開封第一講書人閱讀 152,762評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵戈二,是天一觀的道長舒裤。 經(jīng)常有香客問我,道長觉吭,這世上最難降的妖魔是什么腾供? 我笑而不...
    開封第一講書人閱讀 55,273評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮鲜滩,結(jié)果婚禮上伴鳖,老公的妹妹穿的比我還像新娘。我一直安慰自己徙硅,他們只是感情好榜聂,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評(píng)論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著嗓蘑,像睡著了一般须肆。 火紅的嫁衣襯著肌膚如雪贴汪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,046評(píng)論 1 285
  • 那天休吠,我揣著相機(jī)與錄音扳埂,去河邊找鬼。 笑死瘤礁,一個(gè)胖子當(dāng)著我的面吹牛阳懂,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播柜思,決...
    沈念sama閱讀 38,351評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼岩调,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了赡盘?” 一聲冷哼從身側(cè)響起号枕,我...
    開封第一講書人閱讀 36,988評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎陨享,沒想到半個(gè)月后葱淳,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,476評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡抛姑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評(píng)論 2 324
  • 正文 我和宋清朗相戀三年赞厕,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片定硝。...
    茶點(diǎn)故事閱讀 38,064評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡皿桑,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蔬啡,到底是詐尸還是另有隱情诲侮,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評(píng)論 4 323
  • 正文 年R本政府宣布箱蟆,位于F島的核電站沟绪,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏顽腾。R本人自食惡果不足惜近零,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望抄肖。 院中可真熱鬧久信,春花似錦、人聲如沸漓摩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽管毙。三九已至腿椎,卻和暖如春桌硫,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背啃炸。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評(píng)論 1 262
  • 我被黑心中介騙來泰國打工铆隘, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人南用。 一個(gè)月前我還...
    沈念sama閱讀 45,511評(píng)論 2 354
  • 正文 我出身青樓膀钠,卻偏偏與公主長得像,于是被迫代替她去往敵國和親裹虫。 傳聞我的和親對(duì)象是個(gè)殘疾皇子肿嘲,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容