首頁 > 軟體

Vue原始碼cached解析

2022-08-13 14:01:21

前言

建立一個純函數的快取版本

主要用途:優化效能——對於之前運算過一次的內容,利用閉包原理,快取起來,避免重複呼叫,造成效能的浪費

  /**
   * 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內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com