摘要:在之前的文章中已經(jīng)介紹過(guò),檢測(cè)的是對(duì)應(yīng)的數(shù)組在二維數(shù)組中的索引,其行為跟一致,不存在于二維數(shù)組中時(shí),返回,否則返回索引值。最后將緩存數(shù)量減少。
昨日我沿著河岸/漫步到/蘆葦彎腰喝水的地方順便請(qǐng)煙囪/在天空為我寫(xiě)一封長(zhǎng)長(zhǎng)的信
潦是潦草了些/而我的心意/則明亮亦如你窗前的燭光/稍有曖昧之處/勢(shì)所難免/因?yàn)轱L(fēng)的緣故
——洛夫《因?yàn)轱L(fēng)的緣故》
本文為讀 lodash 源碼的第七篇,后續(xù)文章會(huì)更新到這個(gè)倉(cāng)庫(kù)中,歡迎 star:pocket-lodash
gitbook也會(huì)同步倉(cāng)庫(kù)的更新,gitbook地址:pocket-lodash
作用與用法在之前的《lodash源碼分析之Hash緩存》介紹過(guò)用 Hash 做緩存的情況,在這篇文章中介紹過(guò),lodash 是想要實(shí)現(xiàn)和 Map 一樣的接口。
Hash 其實(shí)是用對(duì)象來(lái)做緩存,但是對(duì)象有一個(gè)局限,它的 key 只能是字符串或者 Symbol 類型,但是 Map 是支持各種類型的值來(lái)作為 key,因此 Hash 緩存無(wú)法完全模擬 Map 的行為,當(dāng)遇到 key 為數(shù)組、對(duì)象等類型時(shí),Hash 就無(wú)能為力了。
因此,在不支持 Map 的環(huán)境下,lodash 實(shí)現(xiàn)了 ListCache 來(lái)模擬,ListCache 本質(zhì)上是使用一個(gè)二維數(shù)組來(lái)儲(chǔ)存數(shù)據(jù)。
ListCache 的調(diào)用方式和 Hash 一致:
new ListCache([ [{key: "An Object Key"}, 1], [["An Array Key"],2], [function(){console.log("A Function Key")},3] ])
返回的結(jié)果如下:
{ size: 3, __data__: [ [{key: "An Object Key"}, 1], [["An Array Key"],2], [function(){console.log("A Function Key")},3] ] }
結(jié)構(gòu)和 Hash 類似,但是 __data__ 變成了數(shù)組。
接口設(shè)計(jì)ListCache 的接口與 Hash 一樣,同樣實(shí)現(xiàn)了 Map 的數(shù)據(jù)管理接口。
依賴import assocIndexOf from "./assocIndexOf.js"
《lodash源碼分析之自減的兩種形式》
源碼分析class ListCache { 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__ = [] this.size = 0 } delete(key) { const data = this.__data__ const index = assocIndexOf(data, key) if (index < 0) { return false } const lastIndex = data.length - 1 if (index == lastIndex) { data.pop() } else { data.splice(index, 1) } --this.size return true } get(key) { const data = this.__data__ const index = assocIndexOf(data, key) return index < 0 ? undefined : data[index][1] } has(key) { return assocIndexOf(this.__data__, key) > -1 } set(key, value) { const data = this.__data__ const index = assocIndexOf(data, key) if (index < 0) { ++this.size data.push([key, value]) } else { data[index][1] = value } return this } }constructor
構(gòu)造器跟 Hash 一模一樣,都是先調(diào)用 clear 方法,然后調(diào)用 set 方法,往緩存中加入初始數(shù)據(jù)。
這里調(diào)用 clear 方法并不是說(shuō)為了清除數(shù)據(jù),還沒(méi)開(kāi)始使用這個(gè)類,肯定是沒(méi)有數(shù)據(jù)的,而是為了初始化 __data__ 和 size 這兩個(gè)屬性。
clearclear() { this.__data__ = [] this.size = 0 }
clear 是為了清空緩存。
其實(shí)就是將容器 __data__ 設(shè)置成空數(shù)組,在 Hash 中是設(shè)置為空對(duì)象,將緩存數(shù)量 size 設(shè)置為 0 。
hashas(key) { return assocIndexOf(this.__data__, key) > -1 }
has 用來(lái)判斷是否已經(jīng)有緩存數(shù)據(jù),如果緩存數(shù)據(jù)已經(jīng)存在,則返回 true 。
在之前的文章中已經(jīng)介紹過(guò),assocIndexOf 檢測(cè)的是對(duì)應(yīng) key 的 [key,value] 數(shù)組在二維數(shù)組中的索引,其行為跟 indexOf 一致,不存在于二維數(shù)組中時(shí),返回 -1 ,否則返回索引值。因此可以用是否大于 -1 來(lái)判斷指定 key 的數(shù)據(jù)是否已經(jīng)被緩存。
setset(key, value) { const data = this.__data__ const index = assocIndexOf(data, key) if (index < 0) { ++this.size data.push([key, value]) } else { data[index][1] = value } return this }
set 用來(lái)增加或者更新需要緩存的值。set 的時(shí)候需要同時(shí)維護(hù) size 和緩存的值。
跟 has 一樣,調(diào)用 assocIndexOf 找到指定 key 的索引值,如果小于 0 ,則表明指定的 key 尚未緩存,需要將緩存數(shù)量 size 加 1 ,然后將緩存數(shù)據(jù)加入到 this.__data__ 的末尾。
否則更新 value 即可。
強(qiáng)迫癥看到 has 用大于 -1 來(lái)判斷,而這里用小于 0 來(lái)判斷可能會(huì)相當(dāng)難受。
getget(key) { const data = this.__data__ const index = assocIndexOf(data, key) return index < 0 ? undefined : data[index][1] }
get 方法是從緩存中取值。
如果緩存中存在值,則返回緩存中的值,否則返回 undefined 。
deletedelete(key) { const data = this.__data__ const index = assocIndexOf(data, key) if (index < 0) { return false } const lastIndex = data.length - 1 if (index == lastIndex) { data.pop() } else { data.splice(index, 1) } --this.size return true }
delete 方法用來(lái)刪除指定 key 的緩存。成功刪除返回 true, 否則返回 false。 刪除操作同樣需要維護(hù) size 屬性。
首先調(diào)用 assocIndexOf 來(lái)找到緩存的索引。
如果索引小于 0 ,表明沒(méi)有緩存,刪除不成功,直接返回 false 。
如果要?jiǎng)h除的緩存是緩存中的最后一項(xiàng),則直接調(diào)用 pop 方法,將緩存刪除,否則將調(diào)用 splice 方法將對(duì)應(yīng)位置的緩存刪除。
為什么不直接都用 splice 來(lái)刪除數(shù)據(jù)呢?因?yàn)?pop 的性能比 splice 好,我簡(jiǎn)單測(cè)了一下,大概快 17% 左右。
有興趣的可以看下 pop 和 splice 的規(guī)范,splice 要比 pop 做的事情要多。
從這里又看出了 lodash 對(duì)性能的極致追求。
最后將緩存數(shù)量 size 減少 1 。
參考Set 和 Map 數(shù)據(jù)結(jié)構(gòu)
MDN: 使用對(duì)象
ECMAScript5.1中文版 + ECMAScript3 + ECMAScript(合集)
License署名-非商業(yè)性使用-禁止演繹 4.0 國(guó)際 (CC BY-NC-ND 4.0)
最后,所有文章都會(huì)同步發(fā)送到微信公眾號(hào)上,歡迎關(guān)注,歡迎提意見(jiàn):
作者:對(duì)角另一面
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/92485.html
摘要:接口設(shè)計(jì)同樣實(shí)現(xiàn)了跟一致的數(shù)據(jù)管理接口,如下依賴源碼分析之緩存源碼分析之緩存源碼分析是否使用這個(gè)函數(shù)用來(lái)判斷是否使用緩存。返回表示使用緩存,返回則使用或者緩存。獲取對(duì)應(yīng)緩存方式的實(shí)例這個(gè)函數(shù)根據(jù)來(lái)獲取儲(chǔ)存了該的緩存實(shí)例。 每個(gè)人心里都有一團(tuán)火,路過(guò)的人只看到煙?!吨翋?ài)梵高·星空之謎》 本文為讀 lodash 源碼的第八篇,后續(xù)文章會(huì)更新到這個(gè)倉(cāng)庫(kù)中,歡迎 star:pocket-...
摘要:接口設(shè)計(jì)同樣實(shí)現(xiàn)了跟一致的數(shù)據(jù)管理接口,如下依賴源碼分析之緩存源碼分析之緩存源碼分析是否使用這個(gè)函數(shù)用來(lái)判斷是否使用緩存。返回表示使用緩存,返回則使用或者緩存。獲取對(duì)應(yīng)緩存方式的實(shí)例這個(gè)函數(shù)根據(jù)來(lái)獲取儲(chǔ)存了該的緩存實(shí)例。 每個(gè)人心里都有一團(tuán)火,路過(guò)的人只看到煙。——《至愛(ài)梵高·星空之謎》 本文為讀 lodash 源碼的第八篇,后續(xù)文章會(huì)更新到這個(gè)倉(cāng)庫(kù)中,歡迎 star:pocket-...
摘要:在之前的文章中已經(jīng)介紹過(guò),檢測(cè)的是對(duì)應(yīng)的數(shù)組在二維數(shù)組中的索引,其行為跟一致,不存在于二維數(shù)組中時(shí),返回,否則返回索引值。最后將緩存數(shù)量減少。 昨日我沿著河岸/漫步到/蘆葦彎腰喝水的地方順便請(qǐng)煙囪/在天空為我寫(xiě)一封長(zhǎng)長(zhǎng)的信 潦是潦草了些/而我的心意/則明亮亦如你窗前的燭光/稍有曖昧之處/勢(shì)所難免/因?yàn)轱L(fēng)的緣故 ——洛夫《因?yàn)轱L(fēng)的緣故》 本文為讀 lodash 源碼的第七篇,后續(xù)文章會(huì)...
摘要:但是在類中,要初始化緩存和設(shè)置緩存都需要提供和組成的二維數(shù)組,因此在類中,提供了一種更方便的緩存設(shè)置方式,只需要提供緩存的值即可。這里構(gòu)造函數(shù)不需要再傳入的二維數(shù)組了,只需要傳入包含所有緩存值的數(shù)組即可。 在世界上所有的民族之中,支配著他們的喜怒選擇的并不是天性,而是他們的觀點(diǎn)。——盧梭《社會(huì)與契約論》 本文為讀 lodash 源碼的第九篇,后續(xù)文章會(huì)更新到這個(gè)倉(cāng)庫(kù)中,歡迎 star...
摘要:但是在類中,要初始化緩存和設(shè)置緩存都需要提供和組成的二維數(shù)組,因此在類中,提供了一種更方便的緩存設(shè)置方式,只需要提供緩存的值即可。這里構(gòu)造函數(shù)不需要再傳入的二維數(shù)組了,只需要傳入包含所有緩存值的數(shù)組即可。 在世界上所有的民族之中,支配著他們的喜怒選擇的并不是天性,而是他們的觀點(diǎn)。——盧梭《社會(huì)與契約論》 本文為讀 lodash 源碼的第九篇,后續(xù)文章會(huì)更新到這個(gè)倉(cāng)庫(kù)中,歡迎 star...
閱讀 2517·2021-09-22 15:41
閱讀 1481·2021-08-19 10:54
閱讀 1796·2019-08-23 15:11
閱讀 3425·2019-08-23 10:23
閱讀 1458·2019-08-22 16:28
閱讀 819·2019-08-22 15:11
閱讀 764·2019-08-22 14:53
閱讀 740·2019-08-22 13:49