国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

lodash源碼分析之緩存方式的選擇

HitenDev / 2327人閱讀

摘要:接口設計同樣實現了跟一致的數據管理接口,如下依賴源碼分析之緩存源碼分析之緩存源碼分析是否使用這個函數用來判斷是否使用緩存。返回表示使用緩存,返回則使用或者緩存。獲取對應緩存方式的實例這個函數根據來獲取儲存了該的緩存實例。

每個人心里都有一團火,路過的人只看到煙。

——《至愛梵高·星空之謎》

本文為讀 lodash 源碼的第八篇,后續文章會更新到這個倉庫中,歡迎 star:pocket-lodash

gitbook也會同步倉庫的更新,gitbook地址:pocket-lodash

前言

在《lodash源碼分析之Hash緩存》和《lodash源碼分析之List緩存》介紹了 lodash 的兩種緩存方式,這兩種緩存方式都實現了和 Map 一致的數據管理接口,其中 List 緩存只在不支持 Map 的環境中使用,那何時使用 Hash 緩存,何時使用 Map 或者 List 緩存呢?這就是 MapCache 類所需要做的事情。

緩存方式的選擇

從之前的分析可以看出,Hash 緩存完全可以用 List 緩存或者 Map 來代替,為什么 lodash 不干脆統一用一種緩存方式呢?

原因是在數據量較大時,對象的存取比 Map 或者數組的性能要好。

因此,ladash 在能夠用 Hash 緩存時,都盡量使用 Hash 緩存,而能否使用 Hash 緩存的關鍵是 key 的類型。

以下便為 lodash 決定使用緩存方式的流程:

首先,判斷 key 的類型,以是否為 string/number/symbol/boolean 類型為成兩撥,如果是以上的類型,再判斷 key 是否等于 __proto__ ,如果不是 __proto__ ,則使用 Hash 緩存。不能為 __proto__ 的原因是,大部分 JS 引擎都以這個屬性來保存對象的原型。

如果不是以上的類型,則判斷 key 是否為 null,如果為 null ,則依然使用 Hash 緩存,其余的則使用 Map 或者 List 緩存。

從上面的流程圖還可以看到,在可以用 Hash 來緩存的 key 中,還以是否為 string 類型分成了兩個 Hash 對象來緩存數據,為什么要這樣呢?

我們都知道,對象的 key 如果不是字符串或者 Symbol 類型時,會轉換成字符串的形式,因此如果緩存的數據中同時存在像數字 1 和字符串 "1" 時,數據都會儲存在字符串 "1" 上。這兩個不同的鍵值,最后獲取的都是同一份數據,這明顯是不行的,因此需要將要字符串的 key 和其他需要轉換類型的 key 分開兩個 Hash 對象儲存。

作用與用法

MapCache 所做的事情有點像函數重載,其調用方式和 HashMapListCache 一致。

new MapCache([
  ["key", "value"],
  [{key: "An Object Key"}, 1],
  [Symbol(),2]
])

所返回的結果如下:

{
  size: 3,
  __data__: {
    string: {
      ... 
    },
    hash: {
      ...
    },
    map: {
      ...  
    }
  }
}

可以看到,__data__ 里根據 key 的類型分成了 stringhashmap 三種類型來儲存數據。其中 stringhash 都是 Hash 的實例,而 map 則是 mapListCache 的實例。

接口設計

MapCache 同樣實現了跟 Map 一致的數據管理接口,如下:

依賴
import Hash from "./Hash.js"
import ListCache from "./ListCache.js"

《lodash源碼分析之Hash緩存》

《lodash源碼分析之List緩存》

源碼分析
function getMapData({ __data__ }, key) {
  const data = __data__
  return isKeyable(key)
    ? data[typeof key == "string" ? "string" : "hash"]
    : data.map
}

function isKeyable(value) {
  const type = typeof value
  return (type == "string" || type == "number" || type == "symbol" || type == "boolean")
    ? (value !== "__proto__")
    : (value === null)
}

class MapCache {

  constructor(entries) {
    let index = -1
    const length = entries == null ? 0 : entries.length

    this.clear()
    while (++index < length) {
      const entry = entries[index]
      this.set(entry[0], entry[1])
    }
  }

  clear() {
    this.size = 0
    this.__data__ = {
      "hash": new Hash,
      "map": new (Map || ListCache),
      "string": new Hash
    }
  }

  delete(key) {
    const result = getMapData(this, key)["delete"](key)
    this.size -= result ? 1 : 0
    return result
  }

  get(key) {
    return getMapData(this, key).get(key)
  }

  has(key) {
    return getMapData(this, key).has(key)
  }

  set(key, value) {
    const data = getMapData(this, key)
    const size = data.size

    data.set(key, value)
    this.size += data.size == size ? 0 : 1
    return this
  }
}
是否使用Hash
function isKeyable(value) {
  const type = typeof value
  return (type == "string" || type == "number" || type == "symbol" || type == "boolean")
    ? (value !== "__proto__")
  : (value === null)
}

這個函數用來判斷是否使用 Hash 緩存。返回 true 表示使用 Hash 緩存,返回 false 則使用 Map 或者 ListCache 緩存。

這個在流程圖上已經解釋過,不再作詳細的解釋。

獲取對應緩存方式的實例
function getMapData({ __data__ }, key) {
  const data = __data__
  return isKeyable(key)
    ? data[typeof key == "string" ? "string" : "hash"]
    : data.map
}

這個函數根據 key 來獲取儲存了該 key 的緩存實例。

__data__ 即為 MapCache 實例中的 __data__ 屬性的值。

如果使用的是 Hash 緩存,則類型為字符串時,返回 __data__ 中的 string 屬性的值,否則返回 hash 屬性的值。這兩者都為 Hash 實例。

否則返回 map 屬性的值,這個可能是 Map 實例或者 ListCache 實例。

constructor
constructor(entries) {
  let index = -1
  const length = entries == null ? 0 : entries.length

  this.clear()
  while (++index < length) {
    const entry = entries[index]
    this.set(entry[0], entry[1])
  }
}

構造器跟 HashListCache 一模一樣,都是先調用 clear 方法,然后調用 set 方法,往緩存中加入初始數據。

clear
clear() {
  this.size = 0
  this.__data__ = {
    "hash": new Hash,
    "map": new (Map || ListCache),
    "string": new Hash
  }
}

clear 是為了清空緩存。

這里值得注意的是 __data__ 屬性,使用 hashstringmap 來保存不同類型的緩存數據,它們之間的區別上面已經論述清楚。

這里也可以清晰地看到,如果在支持 Map 的環境中,會優先使用 Map ,而不是 ListCache

has
has(key) {
  return getMapData(this, key).has(key)
}

has 用來判斷是否已經有緩存數據,如果緩存數據已經存在,則返回 true

這里調用了 getMapData 方法,獲取到對應的緩存實例(HashMap 或者 ListCache 的實例),然后調用的是對應實例中的 has 方法。

set
set(key, value) {
  const data = getMapData(this, key)
  const size = data.size

  data.set(key, value)
  this.size += data.size == size ? 0 : 1
  return this
}

set 用來增加或者更新需要緩存的值。set 的時候需要同時維護 size 和緩存的值。

這里除了調用對應的緩存實例的 set 方法來維護緩存的值外,還需要維護自身的 size 屬性,如果增加值,則加 1

get
get(key) {
  return getMapData(this, key).get(key)
}

get 方法是從緩存中取值。

同樣是調用對應的緩存實例中的 get 方法。

delete
delete(key) {
  const result = getMapData(this, key)["delete"](key)
  this.size -= result ? 1 : 0
  return result
}

delete 方法用來刪除指定 key 的緩存。成功刪除返回 true, 否則返回 false。 刪除操作同樣需要維護 size 屬性。

同樣是調用對應緩存實例中的 delete 方法,如果刪除成功,則需要將自身的 size 的值減少 1

參考 License

署名-非商業性使用-禁止演繹 4.0 國際 (CC BY-NC-ND 4.0)

最后,所有文章都會同步發送到微信公眾號上,歡迎關注,歡迎提意見:

作者:對角另一面

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/61921.html

相關文章

  • lodash源碼分析緩存使用方式進一步封裝

    摘要:但是在類中,要初始化緩存和設置緩存都需要提供和組成的二維數組,因此在類中,提供了一種更方便的緩存設置方式,只需要提供緩存的值即可。這里構造函數不需要再傳入的二維數組了,只需要傳入包含所有緩存值的數組即可。 在世界上所有的民族之中,支配著他們的喜怒選擇的并不是天性,而是他們的觀點。——盧梭《社會與契約論》 本文為讀 lodash 源碼的第九篇,后續文章會更新到這個倉庫中,歡迎 star...

    neroneroffy 評論0 收藏0
  • lodash源碼分析緩存使用方式進一步封裝

    摘要:但是在類中,要初始化緩存和設置緩存都需要提供和組成的二維數組,因此在類中,提供了一種更方便的緩存設置方式,只需要提供緩存的值即可。這里構造函數不需要再傳入的二維數組了,只需要傳入包含所有緩存值的數組即可。 在世界上所有的民族之中,支配著他們的喜怒選擇的并不是天性,而是他們的觀點。——盧梭《社會與契約論》 本文為讀 lodash 源碼的第九篇,后續文章會更新到這個倉庫中,歡迎 star...

    wapeyang 評論0 收藏0
  • lodash源碼分析緩存方式選擇

    摘要:接口設計同樣實現了跟一致的數據管理接口,如下依賴源碼分析之緩存源碼分析之緩存源碼分析是否使用這個函數用來判斷是否使用緩存。返回表示使用緩存,返回則使用或者緩存。獲取對應緩存方式的實例這個函數根據來獲取儲存了該的緩存實例。 每個人心里都有一團火,路過的人只看到煙。——《至愛梵高·星空之謎》 本文為讀 lodash 源碼的第八篇,后續文章會更新到這個倉庫中,歡迎 star:pocket-...

    AdolphLWQ 評論0 收藏0
  • lodash源碼分析Hash緩存

    摘要:只接收一個二維數組作為參數,調用方式如下其中子項中的第一項會作為,第二項是需要緩存的值。實例化的結果如下緩存的數量儲存在的對象中。的作用是清空緩存,因此需要將重置為。將緩存的數據設置為空對象。因為在緩存中是以來表示的,因此遇到值為時,返回。 在那小小的夢的暖閣,我為你收藏起整個季節的煙雨。——洛夫《靈河》 本文為讀 lodash 源碼的第四篇,后續文章會更新到這個倉庫中,歡迎 sta...

    cartoon 評論0 收藏0
  • lodash源碼分析Hash緩存

    摘要:只接收一個二維數組作為參數,調用方式如下其中子項中的第一項會作為,第二項是需要緩存的值。實例化的結果如下緩存的數量儲存在的對象中。的作用是清空緩存,因此需要將重置為。將緩存的數據設置為空對象。因為在緩存中是以來表示的,因此遇到值為時,返回。 在那小小的夢的暖閣,我為你收藏起整個季節的煙雨。——洛夫《靈河》 本文為讀 lodash 源碼的第四篇,后續文章會更新到這個倉庫中,歡迎 sta...

    justjavac 評論0 收藏0

發表評論

0條評論

HitenDev

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<