JavaScript弱對映與弱集合知識詳解

2022-06-20 14:00:56
本篇文章給大家帶來了關於的相關知識,其中主要介紹了關於弱對映與弱集合的相關問題,下面一起來看一下,希望對大家有幫助。

【相關推薦:、】

簡單來講,如果一個變數、物件是「不可達」的,那麼這個變數、物件就沒有必要繼續儲存在記憶體中,進而應該被回收。

舉個例子:

let xiaoming = {name:'xiaoming'}//建立一個物件,並用變數xiaoming參照

xiaoming = null	//將變數xiaoming置空,從而使物件{name:'xiaoming'}不可達

//{name:'xiaoming'}物件被回收

如果一個物件被陣列,其他物件參照,只要參照它陣列和物件存在於陣列中,那麼這個物件也就被認為是可達的。

陣列中的物件:

let xiaoming = {name:'xiaoming'}
let arr = [xiaoming]
xiaoming = null //將變數xiaoming置空
//物件{name:'xiaoming'}由於存在於陣列中,並不會被釋放

同樣的,如果我們把一個物件做為Map的鍵,如果Map存在,那麼物件就不會被引擎回收。

Map中的鍵物件:

let xiaoming = {name:'xiaoming'}
let map = new Map()
map.set(xiaoming,'a boy')
xiaoming = null //將變數xiaoming置空
//物件{name:'xiaoming'}由於是map的鍵,並不會被釋放

WeapMap在釋放鍵物件的處理上和Map有著本質上的不同,簡單來講,WeapMap不會因為物件作為鍵而阻止垃圾回收。

WeakMap

WeakMapMap的區別可分為三個方面:

  1. WeakMap只能以物件作為鍵
let weakMap = new WeakMap()
let obj = {name:'obj'}
weakMap.set(obj,'obj as the key')
weakMap.set('str','str as the key')//報錯

程式碼執行結果如下:

在這裡插入圖片描述

可見,當我們使用字串作為key時,程式不能正常執行。

  1. 不阻止引擎對鍵(物件)的回收

也就是說,如果一個物件除了WeakMap的參照之外沒有其他參照,那麼這個物件就會被系統回收。

舉個例子:

let weakMap = new WeakMap()
let obj = {name:'obj'}
weakMap.set(obj,'obj as the key')
obj = null	//將變數obj置空
//此時,物件{name:'obj'}就會被回收
  1. WeakMap支援的方法有限
  • WeakMap不支援迭代
  • WeakMap不支援keys()
  • WeakMap不支援values()
  • WeakMap不支援entires()

所以,我們沒有辦法獲得所有的鍵值對。

WeakMap只能使用如下方法:

  • weakMap.get(key)獲取鍵值對
  • weakMap.set(key,val)設定鍵值對
  • weakMap.delete(key)刪除鍵值對
  • weakMap.has(key)判斷是否存在

之所以要限制WeakMap的資料存取方式,是因為JavaScript引擎釋放物件的時機是無法確定的。

當一個物件失去了所有的參照之後,JavaScript引擎有可能會立即釋放物件佔用的空間,也有可能再等一等。

所以,在某一時刻,WeakMap的元素數量是不能確定的。(試想一下,如果一個物件在失去所有的參照之後,我們遍歷WeakMap的元素,可能會得到不同的結果。)

WeakMap使用案例

WeakMap的應用場景通常是儲存一個「屬於」物件的資料,當這個物件不存在時,「屬於」這個物件的資料也應該隨之釋放。

有一個非常適合使用WeakMap`的歷史故事:「狡兔死,走狗烹;飛鳥盡,良弓藏」。

如果我們用JavaScript程式碼描述這個故事,就應該用WeakMap:

let weakMap = new WeakMap()
let rabbit = {name:'rabbit'}  	//狡兔
let runDog  = {name:'runDog'}	//走狗
let flyBird = {name:'flyBird'}	//飛鳥
let goodBow = {name:'goodBow'}	//良弓
weakMap.set(rabbit,runDog)
weakMap.set(flyBird,goodBow)

rabbit = null	//狡兔死
flyBird = null	//飛鳥盡
//隨即,走狗和良弓都會被釋放,也可能不是立刻就釋放
//這個故事告訴我們,當走狗沒有啥好下場,可能不是立刻就被
//弄死了,但是遲早要弄死

WeakSet

Set相比,WeakSet有以下不同點:

  1. WeakSet只能新增物件元素
  2. WeakSet不阻止系統對元素的回收
  3. WeakSet支援add()has()delete()
  4. WeakSet不支援size屬性和keys()方法

我們可以用WeakMap來驗證一些存在性資訊,或者驗證"是/否"等狀態,例如,我們可以使用WeakMap判斷使用者是否線上:

let onlineUser = new WeakMap()
let zhangSan = {name:'張三'}
let liSi = {name:'李四'}
let wangEr = {name:'王二'}
let maZi = {name:'麻子'}

function login(user){
    ... ...
    onlineUser.add(user)
}

//判斷使用者是否線上
function isOnline(user){
    return onlineUser.has(user)
}

WeakMapWeakSet的侷限性是不能迭代,無法一次性獲取所有元素,當時不影響它們在非常關鍵的地方發揮重要的作用。

總結

  1. WeakMap只能以物件作為鍵,當鍵的所有外部參照丟失後(除了WeakMap以外沒有別的變數參照鍵物件),WeakMap不會阻止引擎對鍵值的回收。一經回收,WeakMap對應的元素就不存在了。
  2. WeakSet只能儲存物件,一旦物件元素丟失外部所有的參照(除了WeakSet以外,沒有別的變數參照元素物件),WeakSet不會阻止引擎對元素的回收。一經回收,WeakSet中對應的元素就消失了。
  3. 它們共同的優點是,可以在合適的場景中降低物件對記憶體的佔用。
  4. 不支援clear()sizekeys()values()等方法

WeakMapWeakSet常常用於儲存「主」物件關聯的資料結構,一旦「主」物件失去意義,相應的關聯資料結構自然刪除。

【相關推薦:、】

以上就是JavaScript弱對映與弱集合知識詳解的詳細內容,更多請關注TW511.COM其它相關文章!