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

資訊專欄INFORMATION COLUMN

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

AdolphLWQ / 1639人閱讀

摘要:接口設(shè)計(jì)同樣實(shí)現(xiàn)了跟一致的數(shù)據(jù)管理接口,如下依賴源碼分析之緩存源碼分析之緩存源碼分析是否使用這個(gè)函數(shù)用來判斷是否使用緩存。返回表示使用緩存,返回則使用或者緩存。獲取對(duì)應(yīng)緩存方式的實(shí)例這個(gè)函數(shù)根據(jù)來獲取儲(chǔ)存了該的緩存實(shí)例。

每個(gè)人心里都有一團(tuán)火,路過的人只看到煙。

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

本文為讀 lodash 源碼的第八篇,后續(xù)文章會(huì)更新到這個(gè)倉庫中,歡迎 star:pocket-lodash

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

前言

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

緩存方式的選擇

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

原因是在數(shù)據(jù)量較大時(shí),對(duì)象的存取比 Map 或者數(shù)組的性能要好。

因此,ladash 在能夠用 Hash 緩存時(shí),都盡量使用 Hash 緩存,而能否使用 Hash 緩存的關(guān)鍵是 key 的類型。

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

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

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

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

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

作用與用法

MapCache 所做的事情有點(diǎn)像函數(shù)重載,其調(diào)用方式和 HashMapListCache 一致。

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

所返回的結(jié)果如下:

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

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

接口設(shè)計(jì)

MapCache 同樣實(shí)現(xiàn)了跟 Map 一致的數(shù)據(jù)管理接口,如下:

依賴
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)
}

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

這個(gè)在流程圖上已經(jīng)解釋過,不再作詳細(xì)的解釋。

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

這個(gè)函數(shù)根據(jù) key 來獲取儲(chǔ)存了該 key 的緩存實(shí)例。

__data__ 即為 MapCache 實(shí)例中的 __data__ 屬性的值。

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

否則返回 map 屬性的值,這個(gè)可能是 Map 實(shí)例或者 ListCache 實(shí)例。

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])
  }
}

構(gòu)造器跟 HashListCache 一模一樣,都是先調(diào)用 clear 方法,然后調(diào)用 set 方法,往緩存中加入初始數(shù)據(jù)。

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

clear 是為了清空緩存。

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

這里也可以清晰地看到,如果在支持 Map 的環(huán)境中,會(huì)優(yōu)先使用 Map ,而不是 ListCache

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

has 用來判斷是否已經(jīng)有緩存數(shù)據(jù),如果緩存數(shù)據(jù)已經(jīng)存在,則返回 true

這里調(diào)用了 getMapData 方法,獲取到對(duì)應(yīng)的緩存實(shí)例(HashMap 或者 ListCache 的實(shí)例),然后調(diào)用的是對(duì)應(yīng)實(shí)例中的 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 的時(shí)候需要同時(shí)維護(hù) size 和緩存的值。

這里除了調(diào)用對(duì)應(yīng)的緩存實(shí)例的 set 方法來維護(hù)緩存的值外,還需要維護(hù)自身的 size 屬性,如果增加值,則加 1

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

get 方法是從緩存中取值。

同樣是調(diào)用對(duì)應(yīng)的緩存實(shí)例中的 get 方法。

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

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

同樣是調(diào)用對(duì)應(yīng)緩存實(shí)例中的 delete 方法,如果刪除成功,則需要將自身的 size 的值減少 1

參考 License

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

最后,所有文章都會(huì)同步發(fā)送到微信公眾號(hào)上,歡迎關(guān)注,歡迎提意見:

作者:對(duì)角另一面

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/92668.html

相關(guān)文章

  • lodash源碼分析緩存使用方式進(jìn)一步封裝

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

    neroneroffy 評(píng)論0 收藏0
  • lodash源碼分析緩存使用方式進(jìn)一步封裝

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

    wapeyang 評(píng)論0 收藏0
  • lodash源碼分析緩存方式選擇

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

    HitenDev 評(píng)論0 收藏0
  • lodash源碼分析Hash緩存

    摘要:只接收一個(gè)二維數(shù)組作為參數(shù),調(diào)用方式如下其中子項(xiàng)中的第一項(xiàng)會(huì)作為,第二項(xiàng)是需要緩存的值。實(shí)例化的結(jié)果如下緩存的數(shù)量?jī)?chǔ)存在的對(duì)象中。的作用是清空緩存,因此需要將重置為。將緩存的數(shù)據(jù)設(shè)置為空對(duì)象。因?yàn)樵诰彺嬷惺且詠肀硎镜模虼擞龅街禐闀r(shí),返回。 在那小小的夢(mèng)的暖閣,我為你收藏起整個(gè)季節(jié)的煙雨。——洛夫《靈河》 本文為讀 lodash 源碼的第四篇,后續(xù)文章會(huì)更新到這個(gè)倉庫中,歡迎 sta...

    cartoon 評(píng)論0 收藏0
  • lodash源碼分析Hash緩存

    摘要:只接收一個(gè)二維數(shù)組作為參數(shù),調(diào)用方式如下其中子項(xiàng)中的第一項(xiàng)會(huì)作為,第二項(xiàng)是需要緩存的值。實(shí)例化的結(jié)果如下緩存的數(shù)量?jī)?chǔ)存在的對(duì)象中。的作用是清空緩存,因此需要將重置為。將緩存的數(shù)據(jù)設(shè)置為空對(duì)象。因?yàn)樵诰彺嬷惺且詠肀硎镜模虼擞龅街禐闀r(shí),返回。 在那小小的夢(mèng)的暖閣,我為你收藏起整個(gè)季節(jié)的煙雨。——洛夫《靈河》 本文為讀 lodash 源碼的第四篇,后續(xù)文章會(huì)更新到這個(gè)倉庫中,歡迎 sta...

    justjavac 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<