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!

推薦閱讀: