Vue源碼cached解析
前言
創建一個純函數的緩存版本
主要用途:優化性能——對於之前運算過一次的內容,利用閉包原理,緩存起來,避免重復調用,造成性能的浪費
/** * Create a cached version of a pure function. */ function cached (fn) { var cache = Object.create(null); return (function cachedFn (str) { var hit = cache[str]; return hit || (cache[str] = fn(str)) }) }
這一段的源碼很短,但是在源碼中使用瞭19處!這就顯得這個函數很重要瞭
參數解釋
傳入參數
fn
:(函數類型)
用於執行需要緩存的方法
str
:字符串類型
傳入函數fn中的參數
返回參數
類型為:函數類型
源碼解釋
首先通過Object.create
創建一個幹凈的空對象出來
然後直接返回一個函數(cachedFn
)
函數內首先定義變量,通過傳入的參數str去訪問創建出來的cache
對象
- 若hit擊中瞭目標,即不為undefined——直接返回,不再調用函數
- 若未擊中,則訪問傳入的
fn
函數,並把函數返回值賦值給cache
對象
實驗解釋
這樣可能比較抽象,我們直接做一個實驗,同樣直接在瀏覽器中做
這一次,我們直接在瀏覽器的源代碼中做——debug
function cached(fn) { var cache = Object.create(null) return( function cachedFn(str) { var hit = cache[str]; return hit || (cache[str] = fn(str)); } ) } var capitalize = cached(function(str) { return str.charAt(0).toUpperCase() + str.slice(1); }) console.log(capitalize("abc"),"第一次訪問") console.log(capitalize("abc"),"第二次訪問")
直接打一個斷點,看看會發生什麼
執行第一次
在第一次運行時,發現cache是一個空的object,然後直接進入瞭立即執行函數cacheFn
中
這裡立即執行函數的作用就是
創建新的作用域,隔離變量——於將var使用變為let
效果一致
str值為abc
,也就是傳入參數fn中的參數
下一步執行,當然就是執行fn函數瞭
我們可以看到這裡的fn函數就是對應capitalize
中的function,將str的參數傳進來
執行的結果就是Abc
右邊執行完成後,賦值給左側的cache[str]
這裡的代碼可以翻譯成,或許更好理解
cache[str] = "Abc"
也就是說,這裡相當於通過方括號屬性訪問器,創建瞭一個不存在的屬性abc
,對應的值是fn返回的Abc
在右側監視的cache
也明顯的多出瞭一個屬性abc
執行第二次
此時我們看見,cache此時是具有屬性abc
的,因此hit的值不再是undefined
第二次時,很明顯的我們可以看見執行過程,沒有再次調用fn函數,也就是說沒有調用capitalize
中的函數,而是直接獲取的緩存。
從而也就做到瞭對性能的優化。
源碼疑問
為什麼cache是有效的,每次調用函數的時候不都創建瞭新的嗎?
這裡其實使用的是閉包的特性。
在調用cached函數時,會在當前函數創建一個cache對象
也就是說,其實cache對象是屬於當前示例中的capitalize
這個我們可以直接在屬性中看出來
我們重新debug一次,這一次關註capitalize
中的值
第一次執行時
第二次執行時
在運行完cache[str] = fn(str)
後,發現的確這裡的值增加瞭一個
因此,我們可以得出結論。
小結:
在每一次調用cached
時,由於閉包函數的特性,使得cached中的變量值不會被清空,而且這個值是在對應的處理方法中的。
因為cache對象是在內部創建的,所以每次調用cached都將是不同的object
各自擁有獨立的緩存空間,而不是全局共用一個
到此這篇關於Vue源碼cached解析的文章就介紹到這瞭,更多相關Vue cached內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- 利用JavaScript為句子加標題的3種方法示例
- Vue常用API、高級API的相關總結
- 微信小程序生命周期和WXS使用實例詳解
- JavaScript原始值與包裝對象的詳細介紹
- JavaScript中的50+個實用工具函數小結