JS尾遞歸的實(shí)現(xiàn)方法及代碼優(yōu)化技巧
本文實(shí)例講述了JS尾遞歸的實(shí)現(xiàn)方法及代碼優(yōu)化技巧。分享給大家供大家參考,具體如下:
在學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)和算法的時(shí)候,我們都知道所有的遞歸都是可以優(yōu)化成棧+循環(huán)的。
對(duì)于特定的遞歸函數(shù),一般我們都是手動(dòng)對(duì)它們進(jìn)行優(yōu)化的。
在學(xué)習(xí)scala的時(shí)候,接觸到尾遞歸的概念。我們只要將遞歸寫(xiě)成尾遞歸方式,編譯器會(huì)自動(dòng)幫助我們優(yōu)化。
ps:并不是所有的遞歸都可以改寫(xiě)成尾遞歸
在js中,尾遞歸通常會(huì)被解釋器優(yōu)化。然而,并不是所有的js解釋器都支持尾遞歸優(yōu)化。
對(duì)于不支持尾遞歸優(yōu)化的環(huán)境,我們需要手動(dòng)將遞歸優(yōu)化成棧+循環(huán)。
這里實(shí)現(xiàn)了一個(gè)通用的方法,將尾遞歸優(yōu)化成棧+循環(huán)。
代碼摘自阮一峰的《ECMAScript入門(mén)》這本書(shū)。
具體代碼如下
function tco(f) { var value; var active = false; var accumulated = []; return function accumulator() { accumulated.push(arguments); if(!active) { active = true; while(accumulated.length) { value = f.apply(this, accumulated.shift()); } active = false; return value; } }; } var sum = tco(function(x, y) { if(y > 0) { return sum(x + 1, y - 1); } else { return x; } }); let res = sum(1, 5) console.info(res);
這段代碼非常精妙!
分析
已知,任何遞歸可以寫(xiě)成循環(huán)+棧。
實(shí)現(xiàn)將任何尾遞歸轉(zhuǎn)換成循環(huán)+棧執(zhí)行而不需要針對(duì)每個(gè)尾遞歸函數(shù)寫(xiě)一個(gè)實(shí)現(xiàn)版本的思路。
困難在于,任何尾遞歸,通用實(shí)現(xiàn)。而不是針對(duì)某一個(gè)遞歸函數(shù)。
要點(diǎn):
棧中保存的數(shù)據(jù),正是遞歸函數(shù)的參數(shù)。
通用實(shí)現(xiàn),那就必須依賴原來(lái)的遞歸函數(shù),循環(huán)的終止條件,正是遞歸的結(jié)束條件。
要將遞歸函數(shù)的參數(shù)入棧,而不修改原來(lái)的遞歸函數(shù),就必須用一個(gè)函數(shù)代替遞歸函數(shù)被調(diào)用,從而取得函數(shù)入?yún)ⅰ?/p>
遞歸函數(shù)的終止條件,每一個(gè)遞歸函數(shù)都不一樣,但是如果遞歸函數(shù)沒(méi)有被再次調(diào)用,說(shuō)明已達(dá)到終止條件。即終止條件和遞歸函數(shù)的調(diào)用有關(guān)聯(lián)。而遞歸函數(shù)每次調(diào)用,都會(huì)將參數(shù)入棧。所以可以根據(jù)棧中是否有元素,推斷是否達(dá)到終止條件。
更多關(guān)于JavaScript相關(guān)內(nèi)容感興趣的讀者可查看本站專(zhuān)題:《JavaScript數(shù)據(jù)結(jié)構(gòu)與算法技巧總結(jié)》、《JavaScript數(shù)學(xué)運(yùn)算用法總結(jié)》、《JavaScript排序算法總結(jié)》、《JavaScript遍歷算法與技巧總結(jié)》、《JavaScript查找算法技巧總結(jié)》及《JavaScript錯(cuò)誤與調(diào)試技巧總結(jié)》
希望本文所述對(duì)大家JavaScript程序設(shè)計(jì)有所幫助。
相關(guān)文章
基于javascript簡(jiǎn)單實(shí)現(xiàn)對(duì)身份證校驗(yàn)
這篇文章主要介紹了基于javascript簡(jiǎn)單實(shí)現(xiàn)對(duì)身份證校驗(yàn)的相關(guān)資料,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-02-02使用JavaScript實(shí)現(xiàn)一個(gè)交互式音樂(lè)播放器
JavaScript,作為前端開(kāi)發(fā)的重要語(yǔ)言,可以實(shí)現(xiàn)許多復(fù)雜的功能,在這篇文章中,我們將一起創(chuàng)建一個(gè)交互式的音樂(lè)播放器,快跟隨小編一起學(xué)習(xí)一下吧2024-01-01原生js 封裝get ,post, delete 請(qǐng)求的實(shí)例
下面小編就為大家?guī)?lái)一篇原生js 封裝get ,post, delete 請(qǐng)求的實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-08-08關(guān)于二級(jí)域名下使用一級(jí)域名下的COOKIE的問(wèn)題
我們通常在使用cookie的時(shí)候一般都只是局限在本站內(nèi)使用,也就是只在一個(gè)域名下使用2011-11-11JS簡(jiǎn)單實(shí)現(xiàn)無(wú)縫滾動(dòng)效果實(shí)例
這篇文章主要介紹了JS簡(jiǎn)單實(shí)現(xiàn)無(wú)縫滾動(dòng)效果,結(jié)合完整實(shí)例形式分析了javascript實(shí)現(xiàn)圖片無(wú)縫滾動(dòng)效果的實(shí)現(xiàn)技巧,涉及javascript結(jié)合時(shí)間函數(shù)定時(shí)觸發(fā)動(dòng)態(tài)修改頁(yè)面元素屬性的相關(guān)操作方法,需要的朋友可以參考下2016-08-08javascript中獲取選中對(duì)象的類(lèi)型
javascript中獲取選中對(duì)象的類(lèi)型...2007-04-04JavaScript中l(wèi)ayer關(guān)閉指定彈出窗口方法總結(jié)
這篇文章主要給大家介紹了關(guān)于JavaScript中l(wèi)ayer關(guān)閉指定彈出窗口方法的相關(guān)資料,layer是layui的一個(gè)彈出層組件,但是可以作為獨(dú)立組件使用,需要的朋友可以參考下2023-10-10js斷點(diǎn)調(diào)試經(jīng)驗(yàn)分享
給大家詳細(xì)分析了一下JS斷電調(diào)試的心得和經(jīng)驗(yàn),有需要的朋友參考一下吧。2017-12-12