
簡單來講,如果一個變數、物件是「不可達」的,那麼這個變數、物件就沒有必要繼續保存在記憶體中,進而應該被回收。
舉個例子:
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和Map的差異可分為三個面向:
WeakMap只能以物件作為鍵let weakMap = new WeakMap()
let obj = {name:'obj'}
weakMap.set(obj,'obj as the key')
weakMap.set('str','str as the key')//報錯程式碼執行結果如下:

可見,當我們使用字串作為key時,程式不能正常執行。
也就是說,如果一個物件除了WeakMap的引用之外沒有其他引用,那麼這個物件就會被系統回收。
舉個例子:
let weakMap = new WeakMap()
let obj = {name:'obj'}
weakMap.set(obj,'obj as the key')
obj = null //將變數obj置空//此時,物件{name:'obj'}就會被回收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`的歷史故事:「狡兔死,走狗烹煮;飛鳥盡,良弓藏」。
如果我們用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 //飛鳥盡//隨即,走狗和良弓都會被釋放,也可能不是立刻就釋放//這個故事告訴我們,當走狗沒有啥好下場,可能不是立刻就被//弄死了,但是遲早要弄死和Set相比, WeakSet有以下不同點:
WeakSet只能加入物件元素WeakSet並不會阻止系統對元素的回收WeakSet支援add() 、 has() 、 delete()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)
} WeakMap和WeakSet的限制是不能迭代,無法一次取得所有元素,當時不影響它們在非常關鍵的地方發揮重要的作用。
WeakMap只能以物件作為鍵,當鍵的所有外部引用遺失後(除了WeakMap以外沒有其他變數引用的鍵物件), WeakMap不會阻止引擎對鍵值的回收。一經回收, WeakMap對應的元素就不存在了。WeakSet只能儲存對象,一旦物件元素遺失外部所有的參考(除了WeakSet以外,沒有別的變數引用元素物件), WeakSet不會阻止引擎對元素的回收。一經回收, WeakSet中對應的元素就消失了。clear() 、 size 、 keys() 、 values()等方法WeakMap和WeakSet常用來儲存「主」物件關聯的資料結構,一旦「主」物件失去意義,對應的關聯資料結構會自然刪除。