閉包是乙個受到保護的變數空間.
從字面意思來看就是封閉和包裹
在函式中定義的變數,在函式外部無法訪問,因此這個函式就構成閉包
###特點:
在函式體內部允許訪問外部的變數,但是外部不能訪問外部的變數
###要解決閉包的什麼問題
就是要訪問到它的資料
###怎麼樣訪問閉包中的資料
兩個模型:
返回乙個函式,用這個函式獲得資料##閉包的應用有兩個模型返回乙個物件,這個物件包含函式,來操作這個資料
1.實現私有資料
2.實現快取資料
2.1閉包做快取
2.2函式名做快取
但是這樣做的效能非常低,我們可以測試下呼叫一次,需要運算多少次
var count = 0;//計數器,只要呼叫一次函式,就讓count++
當fib(1)的時候,執行1次,fib(2),執行3次,
依次類推 1,3,5,9,15,25
根據運算結果,如果求10項需要運算177次
這樣效能會有非常大的問題,每一次計算都要分兩步去完成,而且有個特點不管有沒有算過都要算一遍,都要這樣去計算,那麼如果計算的數字非常大會影響到我們計算的結果
###怎麼樣提高效率呢,讓算過的不再算
把這個函式寫成乙個自呼叫函式
利用陣列快取,因為存的只是資料
var count;
var fib = (function () else else
arr[n] = res;//將計算的結果放到陣列中,那麼下一次在計算的時候直接拿來用,就不用重新計算了
//其實這裡使用鍵值對做快取,取的時候是取出來n,返回也是給n,沒有用push
為啥都是計算3次
因為我們都是直接從快取中去取,而不是通過遞迴去計算
但是用迴圈體現不出差異性,因為快取了,已經計算出了,就不會在計算,等下再給大家畫**釋下為什麼是3次,現在先讓大家體會下這個差異性
0原來是執行177次,現在只要19次,
之前輸入100會崩潰,現在輸入100只要199次
現在的差異看的很明顯了吧,
利用快取功能很大的提高了效率
大家也可以自己做下測試,原理很簡單就是用乙個陣列將已經計算過的值存起來
現在我們再看看為啥都是計算三次吧
因為前兩次[0]和[1]次迴圈已經有值了,從[2]開始,前兩個的值已經有了,所以不用再遞迴了,
每次要做的事情就是先檢查有沒有,沒有再進行運算,運算就遞迴兩次,
遞迴兩次就累積兩次得到的結果馬上放回去,加上當前的計算,一共是三次
下面來看看沒有用閉包的斐波拉契數列
果然有對比才有傷害啊啊啊
接下來再寫個改良版帶有快取的函式
之前是閉包做的快取,我們做實際開發時沒必要
函式也是物件,把共享的資料放到函式名裡
var fib = function (n) else else
fib[n] = res;
fib.len++;//也可以用slice
return res;
}};fib.len = 0;//給函式新增乙個屬性len
優點把閉包去掉了,用函式名儲存資料
缺點:這個函式名誰都可以訪問,誰都可以修改這個資料
但是用閉包優點是除了fib這個函式誰都不能訪問
順便一提: jquery裡面有個createcache也是用這種實現的哦
利用沙箱模式進行優化,保護資料
矩陣快速冪(以斐波那契數列為例)
問題描述 小 w 發現了乙個神奇的數列 1 2 3,1 1,2 1 這就是著名的 fibonacci sequence 眾所周知,小 m 的數學超級超級好,於是給小 w 出了一道題 給小 w 兩個數 x,y,其中 x y 2 31 1。小 w 任務就是求出 fibonacci 數列第 x y 項的和...
以斐波那契數列為例 淺嚐記憶化搜尋
記憶化搜尋 演算法上依然是搜尋的流程,但是搜尋到的一些解用動態規劃的那種思想和模式作一些儲存。一般說來,動態規劃總要遍歷所有的狀態,而搜尋可以排除一些無效狀態。更重要的是搜尋還可以剪枝,可能剪去大量不必要的狀態,因此在空間開銷上往往比動態規劃要低很多。記憶化演算法在求解的時候還是按著自頂向下的順序,...
以斐波那契數列為例帶你入門動態規劃
我們先來使用遞迴的方法實現斐波那契數列 遞迴解決斐波那契問題 public static int f int n 遞迴求值的缺點是什麼呢?就是大量數值會被重複計算。舉個例子,我們在計算f 5 的時候計算了f 4 和f 3 在計算f 4 的時候又計算了f 3 和f 2 這裡的f 4 就被重複計算了。如...