JavaScript 中強引用:物件的引用在JavaScript 中是強引用,也就是将一个引用对象通过变量或常量保存
時,那麼這個變數或常數就是強引用,這個物件就不會被回收。
JavaScript 中弱引用: WeakMaps 和WeakSets 是我們在JavaScript 使用弱引用唯一途徑,将一个对象作为键添加
WeakMap 或WeakSet 並不能防止這些物件被回收。
強引用就是一個小孩A牽著一條狗,他們之間透過狗鏈兒連著。
弱引用就是,旁邊有個人B指著A牽的狗,說:嘿,那有一隻狗,B指向那隻狗,但他們之間沒有是指綁在一起的東西。
當A放開狗鏈,狗就會跑掉(被垃圾回收),不管B是不是還指著。
但是,當B不再指著那隻狗,狗還被A牽著,不會影響它是否跑掉。
let people = {name:'張三',age:25} let people1 = people;
在上面的程式碼中我們將{name:'张三',age:25}
賦值給變數people時,記憶體中會存在一條線將它們連接起來:
然後建立people1變量,將people賦值給people1,相當於people1也引用這個物件:
我們再來看當我們使用ES6新引入的類型WeakSet和WeakMap在儲存引用值時,是什麼樣的情況。
let people = {name:'張三',age:25} let people1 = people; let set = new WeakSet(); set.add(people);
我們新建了一個WeakSet()實例,透過add方法將會加入了people,people對應的參考值是{name:'张三',age:25}
。
可以看到:set實例中的值{name:'张三',age:25}
引用指向於{name:'张三',age:25}
(在實際記憶體中他指向的是該資料的棧的指標引用,該堆疊指向對應堆中的對應的那個位址的值)。而需要特別注意的是,這條弱引用的「線」是透明的,這是什麼意思?他和強引用的差別在哪裡?
一句話概述:強引用被{name:'张三',age:25}
這個引用認可為一個“連接”,而弱引用不被認可。即該引用並不知道它被set實例所引用。
這說明垃圾回收也不知道該引用被set實例所引用。那麼如果該引用的所有強引用連接都被斷開了(變數被賦值為null或其他情況),那麼該引用會被當作垃圾銷毀,即使set實例還在引用著該引用。
let people = {name:'張三',age:25} let people1 = people; let set = new WeakSet(); set.add(people); people = null; people1 = null;
我們把強引用都斷開會出現什麼情況呢?
因為所有的強引用都斷開了,那麼垃圾回收認為該引用{name:'张三',age:25}
不需要了,就會將他銷毀。那麼對應的set實例所用到的該引用也都不復存在了,即使set實例還在使用該引用。
1、WeakSet中對象的引用是弱引用,也就是說,即使weakset“引用”了某個對象,但垃圾回收不把這種引用計為“引用”,只要其他地方沒有強引用這個對象,該對象就不可達,任何時刻可能被回收;只能儲存引用類型,且不可枚舉、不可清除。
2.WeakMap和Map相似,不過不可枚舉、不可清空、對key所引用的物件是弱引用。
3.WeakSet 適合暫時存放一組對象,以及存放跟對象綁定的資訊。只要這些物件在外部消失,它在WeakSet 裡面的參考就會自動消失。 由於上面這個特點,WeakSet 的成員是不適合引用的,因為它會隨時消失。
4.強引用有時會忘記取消引用,導致記憶體無法釋放,進而可能引發記憶體洩漏。而弱引用,不計入垃圾回收機制,所以就不存在這個問題。