摘要:只接收一個二維數組作為參數,調用方式如下其中子項中的第一項會作為,第二項是需要緩存的值。實例化的結果如下緩存的數量儲存在的對象中。的作用是清空緩存,因此需要將重置為。將緩存的數據設置為空對象。因為在緩存中是以來表示的,因此遇到值為時,返回。
在那小小的夢的暖閣,我為你收藏起整個季節的煙雨。——洛夫《靈河》
本文為讀 lodash 源碼的第四篇,后續文章會更新到這個倉庫中,歡迎 star:pocket-lodash
gitbook也會同步倉庫的更新,gitbook地址:pocket-lodash
作用與用法Hash 顧名思義,就是要有一個離散的序列,根據 key 來儲取數據。而在 javascript 中,最適合的無疑是對象了。
Hash 在 lodash 的 .internal 文件夾中,作為內部文件來使用。lodash 會根據不同的數據類型選擇不同的緩存方式,Hash 便是其中的一種方式,這種方式只能緩存 key 的類型符合對象鍵要求的數據。
Hash 只接收一個二維數組作為參數,調用方式如下:
new Hash([["tes1", 1],["test2",2],["test3",3]])
其中子項中的第一項會作為 key ,第二項是需要緩存的值。
Hash 實例化的結果如下:
{ size: 3, __data__: { test1: 1, test2: 2, test3: 3 } }
緩存的數量儲存在 __data__ 的對象中。
Hash與Map后面將會講到,除了使用 Hash 方式緩存數據外,還會用到 Map,lodash 在設計 Hash 的數據管理接口時,也與 Map 的接口一致,但是不會包含 Map 的遍歷方法。
先來看看這些接口都有那些:
源碼const HASH_UNDEFINED = "__lodash_hash_undefined__" class Hash { 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.__data__ = Object.create(null) this.size = 0 } delete(key) { const result = this.has(key) && delete this.__data__[key] this.size -= result ? 1 : 0 return result } get(key) { const data = this.__data__ const result = data[key] return result === HASH_UNDEFINED ? undefined : result } has(key) { const data = this.__data__ return data[key] !== undefined } set(key, value) { const data = this.__data__ this.size += this.has(key) ? 0 : 1 data[key] = value === undefined ? HASH_UNDEFINED : value return this } } export default Hashconstructor
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]) } }
在 constructor 中并沒有看到初始化 __data__ 屬性和 size 屬性,這個其實在 clear 方法中初始化了,后面會解釋。
接著遍歷傳入的二維數組,調用 set 方法,初始化緩存的值。將子項的第一項作為 key ,第二項為緩存的值。
clearclear() { this.__data__ = Object.create(null) this.size = 0 }
clear 的作用是清空緩存,因此需要將 size 重置為 0。
將緩存的數據 __data__ 設置為空對象。
這里并沒有用 this.__data__ = {} 置空,而是調用了 Object.create 方法,并且將 null 作為參數。我們都知道, Object.create 的第一個參數為創建對象的原型對象,傳入 null 的時候,返回的就是一個真空對象,即沒有原型的對象,因此不會有原型屬性的干擾,用來做緩存對象十分適合。
hashas(key) { const data = this.__data__ return data[key] !== undefined }
has 用來判斷是否已經有緩存數據,如果緩存數據已經存在,則返回 true 。
判斷也十分簡單,只需要判斷取出來的值是否為 undefined 即可。
這個判斷有一個坑,后面會講到。
setset(key, value) { const data = this.__data__ this.size += this.has(key) ? 0 : 1 data[key] = value === undefined ? HASH_UNDEFINED : value return this }
set 用來增加或者更新需要緩存的值。set 的時候需要同時維護 size 和在緩存的值。
首先調用 has 方法,判斷對應的 key 是否已經被緩存過,如果已經緩存過,則 size 保持不變,否則 size 加 1 。
緩存值其實就是設置緩存對象 this.__data__ 對應 key 屬性的值。
在 has 中說到用 data[key] !== undefined 有一個坑,因為要緩存的值也可以是 undefined ,如果不做處理,肯定會導致判斷錯誤。
lodash 的處理方式是將 undefined 的值轉換成 HASH_UNDEFINED ,也即一開始便定義的 __lodash_hash_undefined__ 字符串來儲存。
所以在緩存中,是用字符串 __lodash_hash_undefined__ 來替代 undefined 的。
set 在最后還將實例 this 返回,以支持鏈式操作。
getget(key) { const data = this.__data__ const result = data[key] return result === HASH_UNDEFINED ? undefined : result }
get 方法是從緩存中取值。
取值其實就是返回緩存對象中對應 key 的值即可。因為 undefined 在緩存中是以 __lodash_hash_undefined__ 來表示的,因此遇到值為 __lodash_hash_undefined__ 時,返回 undefined 。
其實這樣還是有小小的問題的,如果需要緩存的值剛好是 __lodash_hash_undefined__,那取出來的值跟預設的就不一致了。但是這樣情況應該很少出現吧。
deletedelete(key) { const result = this.has(key) && delete this.__data__[key] this.size -= result ? 1 : 0 return result }
delete 方法用來刪除指定 key 的緩存。成功刪除返回 true, 否則返回 false。 刪除操作同樣需要維護 size 屬性和緩存值。
首先調用 has 方法來判斷緩存是否存在,如果存在,用 delete 操作符將 __data__ 中對應的屬性刪除。
delete 操作符在成功刪除屬性時會返回 true,如果成功刪除,則需要將 size 減少 1 。
參考Set 和 Map 數據結構
Object.create()
License署名-非商業性使用-禁止演繹 4.0 國際 (CC BY-NC-ND 4.0)
最后,所有文章都會同步發送到微信公眾號上,歡迎關注,歡迎提意見:
作者:對角另一面
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/90590.html
摘要:但是在類中,要初始化緩存和設置緩存都需要提供和組成的二維數組,因此在類中,提供了一種更方便的緩存設置方式,只需要提供緩存的值即可。這里構造函數不需要再傳入的二維數組了,只需要傳入包含所有緩存值的數組即可。 在世界上所有的民族之中,支配著他們的喜怒選擇的并不是天性,而是他們的觀點。——盧梭《社會與契約論》 本文為讀 lodash 源碼的第九篇,后續文章會更新到這個倉庫中,歡迎 star...
摘要:但是在類中,要初始化緩存和設置緩存都需要提供和組成的二維數組,因此在類中,提供了一種更方便的緩存設置方式,只需要提供緩存的值即可。這里構造函數不需要再傳入的二維數組了,只需要傳入包含所有緩存值的數組即可。 在世界上所有的民族之中,支配著他們的喜怒選擇的并不是天性,而是他們的觀點。——盧梭《社會與契約論》 本文為讀 lodash 源碼的第九篇,后續文章會更新到這個倉庫中,歡迎 star...
摘要:接口設計同樣實現了跟一致的數據管理接口,如下依賴源碼分析之緩存源碼分析之緩存源碼分析是否使用這個函數用來判斷是否使用緩存。返回表示使用緩存,返回則使用或者緩存。獲取對應緩存方式的實例這個函數根據來獲取儲存了該的緩存實例。 每個人心里都有一團火,路過的人只看到煙。——《至愛梵高·星空之謎》 本文為讀 lodash 源碼的第八篇,后續文章會更新到這個倉庫中,歡迎 star:pocket-...
摘要:接口設計同樣實現了跟一致的數據管理接口,如下依賴源碼分析之緩存源碼分析之緩存源碼分析是否使用這個函數用來判斷是否使用緩存。返回表示使用緩存,返回則使用或者緩存。獲取對應緩存方式的實例這個函數根據來獲取儲存了該的緩存實例。 每個人心里都有一團火,路過的人只看到煙。——《至愛梵高·星空之謎》 本文為讀 lodash 源碼的第八篇,后續文章會更新到這個倉庫中,歡迎 star:pocket-...
摘要:只接收一個二維數組作為參數,調用方式如下其中子項中的第一項會作為,第二項是需要緩存的值。實例化的結果如下緩存的數量儲存在的對象中。的作用是清空緩存,因此需要將重置為。將緩存的數據設置為空對象。因為在緩存中是以來表示的,因此遇到值為時,返回。 在那小小的夢的暖閣,我為你收藏起整個季節的煙雨。——洛夫《靈河》 本文為讀 lodash 源碼的第四篇,后續文章會更新到這個倉庫中,歡迎 sta...
閱讀 3469·2023-04-25 21:43
閱讀 3098·2019-08-29 17:04
閱讀 797·2019-08-29 16:32
閱讀 1533·2019-08-29 15:16
閱讀 2144·2019-08-29 14:09
閱讀 2732·2019-08-29 13:07
閱讀 1623·2019-08-26 13:32
閱讀 1320·2019-08-26 12:00