帶你入門 JavaScript ES6 (五) 集合

柳公子發表於2018-01-12

本文同步帶你入門 帶你入門 JavaScript ES6 (五) 集合,轉載請註明出處。

前面我們學習了:

本章我們將學習 ES6 中的 Set(集合)WeakSet 集合 的相關用法及使用場景。

一、概述

Set 集合是 ES6 引入的新的內建物件型別,其特點同數學意義的集合,即集合內所有元素不重複(元素唯一)。

要了解 Set 集合,我們可以先看看陣列,ES6 之前陣列類似於數學意義上 集合,但是差異在於陣列元素值是可重複。

// 陣列
let nums = [1, 2, 3, 4, 5]
console.log(nums)// [1, 2, 3, 4, 5]

nums.push(1)
console.log(nums)// [1, 2, 3, 4, 5, 1]

// 集合
let sLang = new Set([`javascript`, `java`, `c++`, `php`, `javascript`])
console.log(sLang)//  Set {"javascript", "java", "c++", "php"}

對比陣列 nums 和集合 sLang,陣列可以加入重複資料,而集合的所有元素是唯一的不允許重複。

二、Set 集合常用操作

2.1 初始化

① 申明空集合

// 建立空集合
let s = new Set();
console.log(s)// Set {}

s.add(`php`)
console.log(s)//Set {"php"}

② 申明初始值集合

let s = new Set([`php`, `javascript`])
console.log(s)// Set {"php", "javascript"}

③ 語法

new Set([iterable]);

申明集合時,建構函式裡可選接收一個可迭代物件(iterable)

目前支援可迭代協議的可迭代物件有 Array, [Map], Set, String, TypedArray, arguments物件等.

所以一下初始化都是合法的

// string
let str = new Set(`name`)
console.log(str)// Set {"n", "a", "m", "e"}

// set
let strSet = new Set(str)
console.log(strSet)// Set {"n", "a", "m", "e"}

// array
let nums = new Set([1, 2, 3])
console.log(nums)// Set {1, 2, 3}

//arguments
function add(...nums) {
    let args =  new Set(arguments)
    return args
}

console.log(add(1));// Set {1}
console.log(add(1, 2));// Set {1, 2}

2.1 集合操作

常見的操作有新增(add)、刪除(delete)、清空(clear)、判斷是否存在(has)、獲取所有值(values) 及獲取集合元素個數

let lang = new Set([`javascript`, `java`, `c++`, `php`, `javascript`])
console.log(lang)// Set {"javascript", "java", "c++", "php"}

// add
lang.add(`ruby`)
console.log(lang)// Set {"javascript", "java", "c++", "php", "ruby"}

// delete
lang.delete(`java`)
console.log(lang)// Set {"javascript", "c++", "php", "ruby"}

// 判斷是否存在 python,javascript
console.log(`has python: ${lang.has(`python`)}`)// has python: false
console.log(`has javascript: ${lang.has(`javascript`)}`)// has javascript: true

// 獲取所有元素
console.log(lang.values()) // SetIterator {"javascript", "c++", "php", "ruby"}
console.log(lang.keys()) // SetIterator {"javascript", "c++", "php", "ruby"}

// 獲取個數
console.log(lang.size);// 4

// 清空
lang.clear()
console.log(lang);// Set {}

2.2 迭代

Set 集合是一個可迭代的物件,所以可以使用 for of 進行迭代獲取所有資料。

let lang = new Set([`javascript`, `java`, `c++`, `php`, `javascript`])
for (let l of lang) {
    console.log(l);
}

三、 WeakSet 集合

WeakSet 和 普通的 Set 相似,不同點在於:

  • WeakSet 只能新增物件元素
  • WeakSet 無法迭代
  • 沒有 clear() 方法

為什麼沒有 clear 方法,阮一峰老師的 ES6 教程中有過解釋:

WeakSet 中的物件都是弱引用,即垃圾回收機制不考慮 WeakSet 對該物件的引用,也就是說,如果其他物件都不再引用該物件,那麼垃圾回收機制會自動回收該物件所佔用的記憶體,不考慮該物件還存在於 WeakSet 之中。

這是因為垃圾回收機制依賴引用計數,如果一個值的引用次數不為0,垃圾回收機制就不會釋放這塊記憶體。結束使用該值之後,有時會忘記取消引用,導致記憶體無法釋放,進而可能會引發記憶體洩漏。WeakSet 裡面的引用,都不計入垃圾回收機制,所以就不存在這個問題。因此,WeakSet 適合臨時存放一組物件,以及存放跟物件繫結的資訊。只要這些物件在外部消失,它在 WeakSet 裡面的引用就會自動消失。

由於上面這個特點,WeakSet 的成員是不適合引用的,因為它會隨時消失。另外,由於 WeakSet 內部有多少個成員,取決於垃圾回收機制有沒有執行,執行前後很可能成員個數是不一樣的,而垃圾回收機制何時執行是不可預測的,因此 ES6 規定 WeakSet 不可遍歷。

參考資料

Set 物件

WeakSet 物件

Set 和 Map 資料結構

相關文章