每个人心里都有一团火,路过的人只看到烟。
——《至爱梵高·星空之谜》
本文为读 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
所做的事情有点像函数重载,其调用方式和 Hash
、Map
及 ListCache
一致。
new MapCache([
['key', 'value'],
[{key: 'An Object Key'}, 1],
[Symbol(),