迭代器
迭代器是一種特殊對象滚躯,它具有一些專門為迭代過程設(shè)計的專有接口盹愚,所有的迭代器對象都有一個next()方法飞醉,每次調(diào)用都返回一個結(jié)果對象奈懒。結(jié)果對象有兩個屬性:一個是value芍躏,表示下一個將要返回的值邪乍;另一個是done,它是一個布爾類型的值对竣,當(dāng)沒有更多可返回數(shù)據(jù)時返回true春寿。迭代器還會保存一個內(nèi)部指針,用來指向當(dāng)前集合中值的位置困介,每調(diào)用一次next()方法天吓,都會返回下一個可用的值
如果在最后一個值返回后再調(diào)用next()方法,那么返回的對象中屬性done的值為true烦味,屬性value則包含迭代器最終返回的值聂使,這個返回值不是數(shù)據(jù)集的一部分,它與函數(shù)的返回值類似谬俄,是函數(shù)調(diào)用過程中最后一次給調(diào)用者傳遞信息的方法柏靶,如果沒有相關(guān)數(shù)據(jù)則返回undefined
斐波那契數(shù)列
斐波那契數(shù)列 1 1 2 3 5 8 13 ...
話不多說直接進(jìn)入正題
第一種利用遞歸
function fibo(n) {
return n<2 ? 1 : fibo(n-1) + fibo(n-2)
// or return n<2 ? 1 : arguments.callee(n - 1) + arguments.callee(n - 2)
}
console.time('small loop1')
for( let i = 1; i <= 10; i++){
console.log(fibo(n))
}
console.timeEnd('small loop1')
當(dāng)我們計算到第十一個數(shù)時,我們調(diào)用了11次,但是他自身調(diào)用了442次溃论,一共453次屎蜓。
第二種利用迭代
function fibo(n){
let num1 = 1,
num2 = 2,
num3 = 0;
if (n<3) {
num3 = 1
}
for( let i = 3;i<n;i++) {
num3 = num1+num2;
num1 = num2;
num2 = num3
}
return num3
}
第三種 尾遞歸優(yōu)化
遞歸非常耗內(nèi)存,因?yàn)樾枰卤4娉汕习賯€調(diào)用幀钥勋,很容易發(fā)生‘棧溢出’(stack overflow)炬转。但對于尾遞歸優(yōu)化來說,由于只存在一個調(diào)用幀算灸,所以永遠(yuǎn)不會發(fā)生棧溢出扼劈。
function F(n,ac1 = 1,ac2 = 1){
if( n <=1 ){ return ac2}
return F(n - 1,ac2,ac1 +ac2)
}
尾遞歸的實(shí)現(xiàn),往往需要改寫遞歸函數(shù)菲驴,確保最后一步只調(diào)用自身荐吵。做到這一點(diǎn)的方法,就是把所有用到的內(nèi)部變量改寫成函數(shù)的參數(shù).
第四種是我們利用函數(shù)的記憶功能,構(gòu)造帶記憶功能的函數(shù)。
var fibo = function(){
var memo = [1,1]; //存儲我們的結(jié)果隱藏在閉包中先煎,當(dāng)調(diào)用的時候首先先檢查這個結(jié)果是否存在了
var fib = function(n) {
var result = memo[n];
if(typeof result!== 'number') {
result = fib(n-1) + fib(n-2);
memo[n] = result
}
return result;
};
return fib
}()
經(jīng)過測試第一種性能是最差的
20次性能測試
當(dāng)五十次時第一種已經(jīng)無法響應(yīng)出來了
我們?nèi)サ舻谝环N方式再次測試1000次
當(dāng)數(shù)量越來越大時贼涩,記憶函數(shù)的性能就體現(xiàn)出來了
生成器、
1薯蝎、函數(shù)生成器特點(diǎn)是函數(shù)名前面有一個‘*’
2遥倦、通過調(diào)用函數(shù)生成一個控制器
3、調(diào)用next()方法開始執(zhí)行函數(shù)
4良风、遇到y(tǒng)ield函數(shù)將暫停
5谊迄、再次調(diào)用next()繼續(xù)執(zhí)行函數(shù)
消息傳遞
除了暫停和繼續(xù)執(zhí)行外,生成器同時支持傳值烟央。