Set
用於儲存任何型別的唯一值,無論是基本型別還是引用型別。
只有值沒有鍵
嚴格型別檢測儲存,字串數字不等同於數值型數字
儲存的值具有唯一性
遍歷順序是新增的順序,方便儲存回撥函式
其實Set
基礎知識
宣告定義
以下示例演示出如何使用Set
型別儲存資料。
<script> "use strict"; let set = new Set([1, "1", 1, 1, 1, 2, 3, 4, 5, "2"]) // 嚴格型別檢測 1 != "1" console.log(set instanceof Set); // true console.log(set); // set(7) {1, "1", 2, 3, 4, 5, "2"} </script>
新增元素
以下示例將演示如何將任意值元素新增進set
容器中,使用add()
方法進行新增元素的操作。
<script> "use strict"; let set = new Set() set.add(1); set.add(["一","二","三"]); set.add('1'); console.log(set); // Set(3) {1, Array(3), "1"} </script>
獲取數量
使用size
屬性獲取set
容器中的元素個數。
<script> "use strict"; let set = new Set() set.add(1); set.add(["一","二","三"]); set.add('1'); console.log(set); // Set(3) {1, Array(3), "1"} console.log(set.size); // 3 </script>
元素檢測
使用has()
方法檢測元素是否存在。
<script> "use strict"; let set = new Set() set.add(1); set.add(["一", "二", "三"]); set.add('1'); console.log(set); // Set(3) {1, Array(3), "1"} console.log(set.has(["一", "二", "三"])); // 由於是不同的引用地址,故結果為 false let array = ["四", "五", "六"]; set.add(array) console.log(set.has(array)); // 現在的引用地址一致,結果為 true </script>
刪除元素
使用delete()
方法刪除單個元素,返回值為boolean
型別。
<script> "use strict"; let set = new Set() set.add(1); set.add(["一", "二", "三"]); set.add('1'); console.log(set); // Set(3) {1, Array(3), "1"} let res = set.delete(1); // 值型別,可以直接刪除 console.log(res); // true 代表刪除成功 res = set.delete(["一", "二", "三"]) // 引用型別,不可以直接刪除 console.log(res); // false 代表刪除失敗 </script>
清空容器
使用clear()
方法可使set
容器清空。
<script> "use strict"; let set = new Set() set.add(1); set.add(["一", "二", "三"]); set.add('1'); set.clear(); console.log(set.size); // 0 </script>
陣列轉換
轉換資料型別是為了更好的操縱資料,可以使用...
語法或者Array.form()
方法將set
轉換為array
。
我們可以充分的結果set
去重的特性,以及array
豐富的操作方法來任意操縱我們的元素。
如下,我們將set
型別轉換為了陣列。
<script> "use strict"; let set = new Set(["雲崖先生", "男", 18]) let array = [...set]; console.log(array); // (3) ["雲崖先生", "男", 18] console.log(array instanceof Array); // true </script>
將陣列轉換為set
,可以充分利用去重特性。
<script> "use strict"; let array = new Array(1, 1, 1, 2, 2, 3, 4, 5); array = new Set(array); // 去重 array = Array.from(array) console.log(array instanceof Array); // true console.log(array); // (5) [1, 2, 3, 4, 5] </script>
遍歷操作
迭代器建立
使用 keys()/values()/entries()
都可以返回迭代物件,因為set
型別只有值所以 keys
與values
方法結果一致。
<script> "use strict"; let set = new Set(["一", "二", "三", "四", "五"]); let iter_keys = set.keys(); let iter_values = set.values(); let iter_entries = set.entries(); console.log(iter_keys); console.log(iter_values); console.log(iter_entries); </script>
forEach
使用forEach
來迴圈set
容器。
<script> "use strict"; let set = new Set(["一", "二", "三", "四", "五"]); set.forEach(function (index, value) { console.log(index, value); }); </script>
for/of
也可使用for/of
進行迴圈。
<script> "use strict"; let set = new Set(["一", "二", "三", "四", "五"]); for (let i of set) { console.log(i); } </script>
多集合操作
交集
交集代表set1
與set2
共有的部分。
<script> "use strict"; let set1 = new Set(["一", "二", "三", "四", "五"]); let set2 = new Set(["三", "四", "五", "六", "七"]); let new_set = new Set( Array.from(set1).filter(function (value) { return set2.has(value) }) ); console.log(new_set); // Set(3) {"三", "四", "五"} </script>
差集
差集代表一個集合有,另一個集合沒有的部分。
<script> "use strict"; let set1 = new Set(["一", "二", "三", "四", "五"]); let set2 = new Set(["三", "四", "五", "六", "七"]); let new_set = new Set( Array.from(set1).filter(function (value) { return !set2.has(value) }) ); console.log(new_set); // Set(3) Set(2) {"一", "二"} </script>
並集
將兩個集合合併成一個集合,多餘的元素會被剔除,這就是並集。
<script> "use strict"; let set1 = new Set(["一", "二", "三", "四", "五"]); let set2 = new Set(["三", "四", "五", "六", "七"]); let new_set = new Set([...set1,...set2]); console.log(new_set); // Set(7) {"一", "二", "三", "四", "五", "六", "七"} </script>
WeakSet
WeakSet
結構同樣不會儲存重複的值,它的成員必須只能是物件型別的值。
-
垃圾回收不考慮
WeakSet
,即被WeakSet
引用時引用計數器不加一,所以物件不被引用時不管WeakSet
是否在使用都將刪除 -
因為
WeakSet
是弱引用,由於其他地方操作成員可能會不存在,所以不可以進行forEach( )
遍歷等操作 -
也是因為弱引用,
WeakSet
結構沒有keys()
,values()
,entries()
等方法和size
屬性 -
因為是弱引用所以當外部引用刪除時,希望自動刪除資料時使用
Weakset
宣告定義
在 WeakSet
中只能儲存容器型別的物件,即引用型別,不能儲存值型別。
<script> "use strict"; let array = [1,2,3]; let dict = {"k1":"v1","k2":"v2"}; let set = new WeakSet([array,dict]); // 在 WeakSet中只能儲存容器型別的物件,即引用型別。不能儲存值型別 console.log(set); </script>
儲存值型別會丟擲異常。
<script> "use strict"; let array = [1,2,3]; let dict = {"k1":"v1","k2":"v2"}; let symbol = new Symbol(); // 值型別 let set = new WeakSet([array,dict,symbol]); // 在 WeakSet中只能儲存容器型別的物件,即引用型別。不能儲存值型別 console.log(set); // Uncaught TypeError: Symbol is not a constructor </script>
操作方法
方法 | 說明 |
---|---|
add() | 新增一個引用型別物件 |
delete() | 刪除一個引用型別物件 |
has() | 判斷是否存在一個引用型別物件 |
垃圾回收
對於標記清除法來說,存在於WeakSet
中的物件並不會為其增加引用計數,因此也被稱之為弱引用。
當WeakSet
中物件的外部引用計數為0後,垃圾回收機制將清理 WeakSet
容器中的該物件,這會使得WeakSet
容器中該物件將被移除。
<script> "use strict"; let array = [1, 2, 3]; let dict = { "k1": "v1", "k2": "v2" }; let set = new WeakSet([array, dict]); console.log(set); // array還在裡面 array = null; // 清理,引用計數為0 setInterval(() => { console.log(set); // array 不在了 }, 3000); </script>
作用詳解
根據WeakSet
這個特性,我們可以用它來儲存一下經常存取的資料。
當物件被刪除後,我們不用管WeakSet
容器中是否含存有該資料。
示例如下:
將標籤節點全部放入集合中,當在點選的時候新增類並且移出集合設定透明度,當再次點選的時候又將標籤移入集合即可。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <link rel="stylesheet" href="//at.alicdn.com/t/font_1953712_h1wr0ianmf5.css"> <style> body { display: flex; justify-content: center; align-items: center; flex-flow: column wrap; height: 100vh; width: 100vw; } input { border: none; height: 20px; } div { border: 1px solid #ddd; display: flex; justify-content: center; align-items: center; margin-bottom: 10px; padding: 0 5px; width: 200px; height: 30px; } div input { flex: 1; } div input:focus { outline: none; } div i { background-color: rgba(0, 255, 96, 5); padding: 2px; border-radius: 10%; } i.iconfont { font-size: 12px; } .hidden { opacity: .5; } </style> </head> <body> <div> <input type="text"><i class="iconfont icon-shanchu"></i> </div> <div> <input type="text"><i class="iconfont icon-shanchu"></i> </div> <div> <input type="text"><i class="iconfont icon-shanchu"></i> </div> <div> <input type="text"><i class="iconfont icon-shanchu"></i> </div> </body> <script> "use strict"; let divs = document.querySelectorAll("div"); let set = new WeakSet([...divs]); divs.forEach(function (ele) { ele.childNodes[2].addEventListener("click", function (param) { if (set.has(this.parentNode)) { set.delete(this.parentNode); this.parentNode.classList.add('hidden'); } else { set.add(this.parentNode); this.parentNode.classList.remove("hidden"); } }) }) </script> </html>