摘要:采用的生成非波拉契數(shù)列提供了原生的支持,語法非常有特色,關(guān)鍵字后面緊跟一個(gè)星號(hào)。的詳細(xì)介紹參考官網(wǎng)先看如何用這個(gè)黑科技重新實(shí)現(xiàn)非波拉契樹立的生成。在這個(gè)內(nèi)部,我們定義了一個(gè)無限循環(huán),用于計(jì)算非波拉契數(shù)列。
程序員面試系列
Java面試系列-webapp文件夾和WebContent文件夾的區(qū)別?
程序員面試系列:Spring MVC能響應(yīng)HTTP請(qǐng)求的原因?
Java程序員面試系列-什么是Java Marker Interface(標(biāo)記接口)
使用JDK自帶的工具jstack找出造成運(yùn)行程序死鎖的原因
編程面試題:編寫一個(gè)會(huì)造成數(shù)據(jù)庫死鎖的應(yīng)用
JavaScript面試系列:JavaScript設(shè)計(jì)模式之橋接模式和懶加載
面試題:用JavaScript開發(fā)一個(gè)函數(shù),打印非波拉契數(shù)列。
我們只要記住非波拉契數(shù)列的計(jì)算公式,就不難寫出來了:
F(0)=1,F(xiàn)(1)=1, F(n)=F(n-1)+F(n-2)
我寫的JavaScript代碼如下:
var fib = function (a, b) { var _current = a + b; return { current: _current, next: function () { return fib(b, _current); } } }
把當(dāng)前這一輪的計(jì)算結(jié)果存儲(chǔ)到第二行的變量_current里,并通過屬性current返回給調(diào)用者。返回的json對(duì)象除了current屬性外,還有另一個(gè)屬性next,指向一個(gè)閉包函數(shù)調(diào)用。一旦next指向的函數(shù)再次被調(diào)用,則會(huì)再次觸發(fā)數(shù)列的計(jì)算。
var generator = fib(1,1); // 前一行調(diào)用fib(1,1)計(jì)算1+1的結(jié)果為2,將2存儲(chǔ)到_current里通過current屬性返回,所以打印2 // 同時(shí)返回next函數(shù),函數(shù)體為return fib(b, _current); 此時(shí)b為1,_current為2 console.log(generator.current); // 一旦執(zhí)行next函數(shù),則執(zhí)行其指向的return fib(b, _current); 1 + 2 = 3 var result = generator.next(); console.log(result.current); // 打印3
如果要打印10個(gè)非波拉契數(shù)列的值,意味著我要重復(fù)調(diào)用9次fib函數(shù),太麻煩。于是我寫了個(gè)函數(shù)把fib調(diào)用包裹起來。
這個(gè)包裹函數(shù)有兩個(gè)輸入?yún)?shù),n為希望生成非波拉契數(shù)列元素的個(gè)數(shù),第二個(gè)參數(shù)sequence接受一個(gè)函數(shù)。
var take = function(n, sequence) { var result = []; var temp = sequence; for (var i = 0; i < n; i++) { result.push(temp.current); temp = temp.next(); } return result; }
現(xiàn)在我只需要一行語句,就能打印10個(gè)非波拉契數(shù)列的元素出來。
console.log(take(10, fib(1,1)));
采用ES6的GeneratorFunction生成非波拉契數(shù)列ES6提供了原生GeneratorFunction的支持,語法非常有特色,關(guān)鍵字function后面緊跟一個(gè)星號(hào)。GeneratorFunction的詳細(xì)介紹參考官網(wǎng):https://developer.mozilla.org...*
先看如何用GeneratorFunction這個(gè)黑科技重新實(shí)現(xiàn)非波拉契樹立的生成。代碼如下:
var fib_generator = function *(){ var current = 0, next = 1; while(true) { [next, current] = [next+current, next]; yield current; } } var fib = fib_generator(); for(var i = 0; i < 10; i++){ console.log(fib.next().value); }
第5行從語義上非常清晰地體現(xiàn)出了非波拉契數(shù)列的計(jì)算公式:
F(n)=F(n-1)+F(n-2)
然而它是包含在一個(gè)while(true)的無限循環(huán)內(nèi)的,所以這段代碼是如何工作的呢?
最好的學(xué)習(xí)辦法就是單步調(diào)試。
代碼第40行到第47行,我們使用了ES6 function*關(guān)鍵字得到了一個(gè)"function generator"。在這個(gè)generator內(nèi)部,我們定義了一個(gè)無限循環(huán),用于計(jì)算非波拉契數(shù)列。
第49行,我們用()調(diào)用了這個(gè)generator,將結(jié)果存儲(chǔ)在變量fib里。直到此時(shí),function generator的實(shí)現(xiàn)體,即代碼41~45行還沒有得到執(zhí)行。
實(shí)際上,49行的變量lib只是維護(hù)了一個(gè)指向fib_generator的ITERATOR指針。
這個(gè)ITERATOR自帶了一個(gè)名為next的方法,是ES6的原生實(shí)現(xiàn),大家看上圖調(diào)試器里的fib.next顯示的是native code。Functiongenerator的神奇之處在于,當(dāng)next方法被調(diào)用一次,則generator內(nèi)部的函數(shù)體也只會(huì)執(zhí)行一次。
單步執(zhí)行,執(zhí)行一次next方法:
注意調(diào)用棧,此時(shí)我們已經(jīng)進(jìn)入fib_generator函數(shù)體內(nèi)部了:
一旦在FunctionGenerator實(shí)現(xiàn)體內(nèi)部執(zhí)行到y(tǒng)ield關(guān)鍵字,則當(dāng)前計(jì)算結(jié)果作為返回值返回給consumer。也就是說,一旦執(zhí)行遇到y(tǒng)ield,則自動(dòng)從無限循環(huán)中退出。
下列簡單的循環(huán)會(huì)打印10個(gè)非波拉契數(shù)列的元素:
for(var i = 0; i < 10; i++){ var currentResult = fib.next(); console.log(currentResult.value); }
從上面的代碼能看出,yield關(guān)鍵字返回一個(gè)json對(duì)象給消費(fèi)者,該對(duì)象有個(gè)名為name的屬性,包含的是具體計(jì)算的數(shù)值。Json對(duì)象的另一個(gè)屬性名為done,類型為boolean,意思是這個(gè)FunctionGenerator的函數(shù)體執(zhí)行是否已經(jīng)結(jié)束。在我的這個(gè)例子里,每次next調(diào)用的yield返回的Json對(duì)象的done屬性都為false,因?yàn)槲业腇unctionGenerator內(nèi)部是一個(gè)無限循環(huán)。
采用ES6的FunctionGenerator打印出的結(jié)果和常規(guī)寫法一致。
相信您面試的時(shí)候,如果能用ES6的FunctionGenerator完成這道題目,一定能讓面試官對(duì)您刮目相看。
我寫的程序員面試系列Java面試系列-webapp文件夾和WebContent文件夾的區(qū)別?
程序員面試系列:Spring MVC能響應(yīng)HTTP請(qǐng)求的原因?
Java程序員面試系列-什么是Java Marker Interface(標(biāo)記接口)
使用JDK自帶的工具jstack找出造成運(yùn)行程序死鎖的原因
編程面試題:編寫一個(gè)會(huì)造成數(shù)據(jù)庫死鎖的應(yīng)用
JavaScript面試系列:JavaScript設(shè)計(jì)模式之橋接模式和懶加載
要獲取更多Jerry的原創(chuàng)技術(shù)文章,請(qǐng)關(guān)注公眾號(hào)"汪子熙"或者掃描下面二維碼:
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/98589.html
摘要:描述斐波那契數(shù)列由列昂納多斐波那契以兔子繁殖為例子而引入,故又稱為兔子數(shù)列。這個(gè)數(shù)列從第項(xiàng)開始,每一項(xiàng)都等于前兩項(xiàng)之和。遞歸版本遞歸版本使用傳參及默認(rèn)參數(shù),減少冗余元算的同時(shí)也減少了函數(shù)調(diào)用。 描述 斐波那契數(shù)列:1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ... 由列昂納多·斐波那契(Leonardoda Fibonacci)以兔子繁殖為例子...
摘要:今天去面試筆試題斐波那契數(shù)列實(shí)現(xiàn),雖然很簡單?;貋硐胂爰热凰惴ㄟ@么重要那就從這個(gè)開始來記錄自己的算法庫吧。在數(shù)學(xué)上,斐波納契數(shù)列以如下被以遞歸的方法定義,,。斐波拉契算法規(guī)律很簡單,,觀察下數(shù)列值就很容易總結(jié)出來了。 一、寫在前面 算法這塊對(duì)于大多數(shù)程序員(包括我)來說可能都是一個(gè)薄弱的地方,如何彌補(bǔ)尼? 每個(gè)人都知道那就是學(xué)習(xí)、特別是算法沒有任何捷徑可走。 在這記錄平時(shí)自己工作和生...
摘要:根據(jù)該規(guī)則,返回第個(gè)斐波那契數(shù)。尾遞歸函數(shù)調(diào)用自身,稱為遞歸。一個(gè)前端眼中的斐波那契數(shù)列解斐波那契數(shù)列的實(shí)用解法調(diào)用棧尾遞歸和手動(dòng)優(yōu)化尾調(diào)用優(yōu)化譯我從用寫斐波那契生成器中學(xué)到的令人驚訝的件事 斐波那契數(shù)列是以下一系列數(shù)字: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, ... 在種子數(shù)字 0 和 1 ...
摘要:高階函數(shù)函數(shù)式編程中,接受函數(shù)作為參數(shù),或者返回一個(gè)函數(shù)作為結(jié)果的函數(shù)通常就被稱為高階函數(shù)。均屬于高階函數(shù),高階函數(shù)并不神秘,我們?nèi)粘>幊桃矔?huì)用到。參考演算函數(shù)式編程指南入門康托爾哥德爾圖靈永恒的金色對(duì)角線原文函數(shù)與演算 緣起 造了一個(gè)輪子,根據(jù)GitHub項(xiàng)目地址,生成項(xiàng)目目錄樹,直觀的展現(xiàn)項(xiàng)目結(jié)構(gòu),以便于介紹項(xiàng)目。歡迎Star。 repository-tree 技術(shù)棧: ES6 ...
摘要:在上做了一道斐波那契數(shù)列求和的題目,做完之后做了一些簡單的優(yōu)化和用另一種方法實(shí)現(xiàn)。動(dòng)態(tài)規(guī)劃解決方案斐波那契數(shù)列求和除了可以用遞歸的方法解決,還可以用動(dòng)態(tài)規(guī)劃的方法解決。 在codewars上做了一道斐波那契數(shù)列求和的題目,做完之后做了一些簡單的優(yōu)化和用另一種方法實(shí)現(xiàn)。 題目 function fibonacci(n) { if(n==0 || n == 1) r...
閱讀 2799·2021-09-01 10:30
閱讀 1690·2019-08-30 15:52
閱讀 979·2019-08-29 18:40
閱讀 1134·2019-08-28 18:30
閱讀 2405·2019-08-23 17:19
閱讀 1333·2019-08-23 16:25
閱讀 2711·2019-08-23 16:18
閱讀 2988·2019-08-23 13:53