每個人心裡都有一團火,路過的人只看到煙。本文為讀 lodash 原始碼的第八篇,後續文章會更新到這個倉庫中,歡迎 star: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
所做的事情有點像函式過載,其呼叫方式和hash
、map
及listcache
一致。
new mapcache([
['key', 'value'],
[, 1],
[symbol(),2]
])
所返回的結果如下:
,
hash: ,
map:
}}
可以看到,__data__
裡根據key
的型別分成了string
、hash
和map
三種型別來儲存資料。其中string
和hash
都是hash
的例項,而map
則是map
或listcache
的例項。
mapcache
同樣實現了跟map
一致的資料管理介面,如下:
import hash from './hash.js'
import listcache from './listcache.js'
《lodash原始碼分析之hash快取》
《lodash原始碼分析之list快取》
function
getmapdata
(, key)
function
iskeyable
(value)
class mapcache
} clear()
} delete(key)
get(key)
has(key)
set(key, value)
}
function
iskeyable
(value)
這個函式用來判斷是否使用hash
快取。返回true
表示使用hash
快取,返回false
則使用map
或者listcache
快取。
這個在流程圖上已經解釋過,不再作詳細的解釋。
function
getmapdata
(, key)
這個函式根據key
來獲取儲存了該key
的快取例項。
__data__
即為mapcache
例項中的__data__
屬性的值。
如果使用的是hash
快取,則型別為字串時,返回__data__
中的string
屬性的值,否則返回hash
屬性的值。這兩者都為hash
例項。
否則返回map
屬性的值,這個可能是map
例項或者listcache
例項。
constructor(entries)
}
構造器跟hash
和listcache
一模一樣,都是先呼叫clear
方法,然後呼叫set
方法,往快取中加入初始資料。
clear()
}
clear
是為了清空快取。
這裡值得注意的是__data__
屬性,使用hash
、string
和map
來儲存不同型別的快取資料,它們之間的區別上面已經論述清楚。
這裡也可以清晰地看到,如果在支援map
的環境中,會優先使用map
,而不是listcache
。
has(key)
has
用來判斷是否已經有快取資料,如果快取資料已經存在,則返回true
。
這裡呼叫了getmapdata
方法,獲取到對應的快取例項(hash
、map
或者listcache
的例項),然後呼叫的是對應例項中的has
方法。
set(key, value)
set
用來增加或者更新需要快取的值。set
的時候需要同時維護size
和快取的值。
這裡除了呼叫對應的快取例項的set
方法來維護快取的值外,還需要維護自身的size
屬性,如果增加值,則加1
。
get(key)
get
方法是從快取中取值。
同樣是呼叫對應的快取例項中的get
方法。
delete(key)
delete
方法用來刪除指定key
的快取。成功刪除返回true
, 否則返回false
。 刪除操作同樣需要維護size
屬性。
同樣是呼叫對應快取例項中的delete
方法,如果刪除成功,則需要將自身的size
的值減少1
。
署名-非商業性使用-禁止演繹 4.0 國際 (cc by-nc-nd 4.0)
lodash原始碼分析之List快取
昨日我沿著河岸 漫步到 蘆葦彎腰喝水的地方 順便請煙囪 在天空為我寫一封長長的信 潦是潦草了些 而我的心意 則明亮亦如你窗前的燭光 稍有曖昧之處 勢所難免 因為風的緣故 洛夫 因為風的緣故 本文為讀 lodash 原始碼的第七篇,後續文章會更新到這個倉庫中,歡迎 star pocket lodash...
lodash原始碼分析之Number
一 lodash版本 4.17.5 二 函式 1 clamp 1 定義 clamp number,lower upper 2 作用 返回加緊的數字。3 例子。const require lodash console.log clamp 10,1,20 輸出 10 console.log clamp ...
lodash原始碼分析之isArguments
有人命中註定要過平庸的生活,默默無聞,因為他們經歷了痛苦或不幸 有人卻故意這樣做,那是因為他們得到的幸福超過了他們的承受能力。卡爾維諾 煙雲 本文為讀 lodash 原始碼的第二十一篇,後續文章會更新到這個倉庫中,歡迎 star pocket lodash import gettag from in...