[TOC]
>[success] # Weak Set集合(弱引用Set集合)
將**對象**存儲在**Set實例**中與存儲在**變量**中完全一樣,只要**Set實例**中的引用存在,**垃圾回收機制就不能釋放該對象的內存空間**,于是之前提到的**Set類型**可以被看作是一個**強引用的Set集合**。舉個例子:
~~~
let set = new Set(),
key = {a:1};
set.add(key);
console.log(set.size); // 1
key = null // 移除原始引用
console.log(set.size); // 1
// 重新取回原始引用
key = [...set] // [{a:1}]
console.log(key[0]) // {a:1}
~~~
在這個示例中,將變量**key**,設置為**null**時便清除了對初始化對象的引用,但是**Set集合**卻保留了這個引用,你仍然可以使用**展開運算符**將**Set集合**轉換成**數組格式**并從這個**數組**的**首個元素**取出該引用。
大部分情況下這段代碼運行良好,但有時候你會希望**當其他所有引用都不再存在時,讓Set集合中的這些引用隨之消失**,舉個例子,**如果你在Web頁面中通過JavaScript、代碼記錄了一些DOM元素,這些元素有可能被另一段腳本移除,而你不又不希望自己的代碼保留這些DOM元素的最后一個引用。(這個情景被稱作內存泄露)**
為了解決這個問題ES6中引入了另一個類型:**Weak Set集合(弱引用Set集合)**。**Weak Set集合**只儲存**對象**的**弱引用**,并且**不可以儲存原始值**;**集合中的弱引用如果是對象唯一的引用,則會被回收并釋放相應內存**。
>[success] ## 創建Weak Set集合
用**WeakSet**構造函數可以創建**Weak Set** 集合,集合支持**3**個方法:**add()**、**has()**、**delete()**。下面這個示例創建了一個**集合**分別調用這**3**個方法:
~~~
let set = new WeakSet(),
key = {};
// 向集合Set中添加對象
set.add(key);
console.log(set.has(key)); // true
set.delete(key);
console.log(set.has(key)); // false
~~~
**Weak Set集合**的使用方式與**Set集合**類似,可以向**集合**中添加引用,從中**移除引用**,也可以**檢查**集合中是否存在指定對象的引用。
也可以調用**WeakSet**構造函數并傳入一個可迭代對象來創建**WeakSet集合**。
~~~
let key1 = {},
key2 = {},
set = new WeakSet([key1, key2]);
console.log(set.has(key1)) // true
console.log(set.has(key2)) // true
~~~
在這個示例中,向**WeakSet構造函數**傳入一個含有**兩個對象的數組**,最終創建一個包含這兩個對象的**Weak Set集合**。請記住,**WeakSet構造函數**不接受任何**原始值**,如果數組中包含其他**非對象值**,程序會拋出錯誤。
>[success] # 兩種Set集合的不同
兩者區別:
| 方法或屬性 | Set集合 | weak Set集合 |
| --- | --- | --- |
| **集合值**的要求 | **基本類型**和**引用類型** | 只能傳入對象 |
| **是否可迭代**(循環)**for in** 或者**for of** | **是** | **否** |
|**forEach()**|**是**| **否**|
|**size屬性**|**是**| **否**|
**Weak Set集合**的功能看似**受限**,其實這是為了讓它能夠正確地處理內存中的數據。總之如果你需要**跟蹤對象引用**,你更應該使用**Weak Set集合**而不是普通的**Set集合**。
- Javascript基礎篇
- Array數組
- 數組插入值
- filter()
- forEach()
- push()
- pop()
- unshift()
- shift()
- valueOf()
- 面向對象思想
- Javascript 面向對象編程(一):封裝
- Javascript面向對象編程(二):構造函數的繼承
- Javascript面向對象編程(三):非構造函數的繼承
- 解構
- 數組的解構賦值
- 對象的解構賦值
- 函數參數解構
- 字符串的解構賦值
- 數值和布爾值的解構賦值
- 圓括號問題
- 字符串.
- split()
- charAt()
- charCodeAt()
- concat()
- indexOf()
- lastIndexOf()
- match()
- replace()
- includes()
- 初識遞歸
- 渲染ul-li樹形結構
- 異步函數解決方案
- 1. callback回調函數
- 2. ES6 - Promise
- JavaScript高級程序設計(書)
- 在html中使用JavaScript
- script標簽的位置
- 延遲腳本
- 異步腳本
- <noscript>元素
- 基本概念
- 嚴格模式
- 變量詳解
- 數據類型
- typeof操作符
- undefined類型
- Null類型
- Boolean類型
- Number類型
- 深入了解ES6(書)
- var 、let 、 const
- 字符串與正則表達式
- 字符串
- 正則表達式
- 函數
- 函數形參默認值
- 使用不具名參數
- 函數構造器的增強能力
- 擴展運算符
- name屬性
- 明確函數的多重用途
- 塊級函數
- 箭頭函數
- 尾調用優化
- 擴展的對象功能
- 對象類別
- 對象字面量語法的擴展
- ES6對象新增方法
- 重復的對象屬性
- 自有屬性的枚舉順序
- 更強大的原型
- 解構:更方便的數據訪問
- 為什么要用解構?
- 對象解構
- 數組解構
- 混合解構
- 參數解構
- Symbol與Symbol屬性
- 創建Symbol
- Symbol的使用方法
- Symbol全局私有屬性
- Symbol與類型強制轉換
- Symbol屬性檢索
- Symbol的一些構造方法
- Set集合與Map集合
- Set集合
- Weak Set集合(弱引用Set集合)
- Map集合
- JS標準內置對象
- Object 構造函數及屬性
- Object 構造方法
- Symbol 內建對象類的函數及屬性
- Set 構造函數及屬性
- Weak Set 構造函數及屬性
- JS雜項
- 類數組對象
- Class類的理解和使用