【相關推薦:、】
簡單來講,如果一個變數、物件是「不可達」的,那麼這個變數、物件就沒有必要繼續儲存在記憶體中,進而應該被回收。
舉個例子:
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
常常用於儲存「主」物件關聯的資料結構,一旦「主」物件失去意義,相應的關聯資料結構自然刪除。
【相關推薦:、】
以上就是JavaScript弱對映與弱集合知識詳解的詳細內容,更多請關注TW511.COM其它相關文章!