Set 相似於數組,可是成員的 值都是惟一的,沒用重複的值。Set自己是一個構造函數,用來生成Set數據結構。前端
const s = new Set();
[2,3,4,5,6,4,2,2,7].forEach(x => s.add(x))
for (let i of s) {
console.log(i)
} // 2 3 4 5 6 7
// Set 不會添加劇復的值。
複製代碼
Set 函數能夠接受一個數組(或具備 iterable 接口的其餘數據結構)做爲參數,用來初始化,以下:算法
// 實例一
const set = new Set([1,2,3,4,5,5])
[...set] // [1,2,3,4,5]
// 實例二
const items = new Set([1,2,3,3,4])
items.size // 4
// 上面代碼還展現了數組去重的方法
[...new Set(array)]
// 或者字符串去重
[...new Set('aabbcc')].join('')
複製代碼
向 Set 加入值的時候,不會發生類型轉換, 全部**5 和 '5'**兩個不一樣的值。在Set 內部判斷兩個值是否不一樣,使用的算法叫作 'Same-value-zero equality',它和 '==='相似,區別在於 向 Set 加入值的時候認爲 NaN等於自身,而 '===' 則認爲 NaN 不等於自身segmentfault
let set = new Set();
let a = NaN;
let b = NaN;
set.add(a);
set.add(b);
set // Set {NaN}
// 如上,只能向Set中添加一個NaN則說明了剛剛的證實
複製代碼
在 Set中兩個對象老是不相等的。數組
let set = new Set();
set.add({})
set.size // 1
set.add({})
set.size // 2
複製代碼
Set 結構的實例有如下屬性數據結構
Set 實例的方法分爲兩大類:操做方法和遍歷方法函數
Set.prototype.add(value) // 添加某個值,返回 Set 結構自己 Set.prototype.delete(value) // 刪除某個值,返回一個布爾值,表示是否刪除成功 Set.prototype.has(value) // 返回一個布爾值,表示該值是否爲Set的成員 Set.prototype.clear() // 清除全部成員,沒用返回值post
s.add(1).add(2).add(2);
// 注意2被加入了兩次
s.size // 2
s.has(1) // true
s.has(2) // true
s.has(3) // false
s.delete(2);
s.has(2) // false
// Object 和 Set 如何判斷一個鍵的區別
// 對象
const p = {
'w': 1,
'h': 2
}
if(p[a]){
no
}
// Set
const p = new Set()
p.add('w')
p.add('h')
if(p.has(c)){
no
}
複製代碼
Array.from 方法能夠將 Set 結構轉爲數組,以下:this
const items = new Set([1,2,3,4,5])
const array = Array.from(items)
// 數組去重的另一種方法
function d(a){
return Array.from(new Set(a))
}
d([1,2,3,3,5])
複製代碼
Set 結構的實例有四個遍歷方法,用於遍歷成員spa
注意:Set遍歷順序就是插入順序,這個特性在特定狀況很是有用,好比使用Set保存一個回調函數列表,調用時就能保證按照添加順序調用。prototype
上面三個都是返回遍歷器對象,因爲Set結構沒用鍵名,只有鍵值(或者說鍵名和鍵值是同一個值),因此以上方法的行爲徹底一致
let set = new Set(['red', 'green', 'blue']);
for (let item of set.keys()) {
console.log(item);
}
// red
// green
// blue
for (let item of set.values()) {
console.log(item);
}
// red
// green
// blue
for (let item of set.entries()) {
console.log(item);
}
// ["red", "red"]
// ["green", "green"]
// ["blue", "blue"]
複製代碼
注意:Set結構的實例默承認遍歷,它的默認遍歷器生成函數就是它的 values方法,這樣咱們就能夠省略 values,直接用 for...of循環遍歷Set
Set結構的實例和數組同樣,也有 forEach方法,用於對每一個成員執行某種操做,沒用返回值。forEach 能夠用第二個參數表示綁定處理函數內部的 this 對象。
擴展運算符(...)內部使用 for...of循環樣能用於 Set 結構
let arr = [3, 5, 2, 2, 5, 5];
let unique = [...new Set(arr)];
// [3, 5, 2]用來去重操做
// 實現 並集、交集、差集
let a = new Set([1, 2, 3]);
let b = new Set([4, 3, 2]);
// 並集
let union = new Set([...a, ...b]);
// Set {1, 2, 3, 4}
// 交集
let intersect = new Set([...a].filter(x => b.has(x)));
// set {2, 3}
// 差集
let difference = new Set([...a].filter(x => !b.has(x)));
// Set {1}
複製代碼
若是想在遍歷操做中同步改變原理的Set結構,只能利用原有的Set結構映射一個新的結構,而後賦值給原來的Set,另外一個就是經過 Array.from方法。
// 方法一
let set = new Set([1, 2, 3]);
set = new Set([...set].map(val => val * 2));
// set的值是2, 4, 6
// 方法二
let set = new Set([1, 2, 3]);
set = new Set(Array.from(set, val => val * 2));
// set的值是2, 4, 6
複製代碼
WeakSet 結構與Set相似,也不是重複的值的集合,可是和Set有兩個區別,第一個它的成員只能爲對象,另外一個它的對象都是弱印象,即垃圾回收機制不考慮 WeakSet對該對象的引用,通俗的講就是,若是該對象沒用在其餘對象中被引用,那麼該對象就會被回收,不會考慮這個對象是否在 WeakSet中。
依賴於垃圾回收進制依賴引用計數,若是一個值的引用次數不爲0,那麼就不會被回收,可是有的時候,結束使用該值後,會忘記取消引用,就會致使內存沒法釋放從而致使內存泄漏。可是 WeakSet裏面的而引用不會計入垃圾回收機制,因此適合存放臨時的對象,一旦外部消失,那麼WeakSet裏面的引用就會自動消失。
基於以上的特色,WeakSet 成員不適合被引用,因此 WeakSet沒法被遍歷。
它也是一個構造函數,能夠經過 new 來建立
const ws = new WeakSet()
// 作爲構造函數,WeakSet
能夠接受一個數組或相似數組的對象做爲參數,該數組的全部成員,
都會自動成爲 WeakSet實例對象的成員。
複製代碼
注意:只能是數組的成員成爲WeakSet的成員,而不是 a 數組自己,這就意味着,數組的成員只能是對象。
注意: WeakSet 一樣沒有size 屬性,不能遍歷其成員。
JavaScript的對象,本質上是鍵值對的集合,可是傳統上只能字符串當作鍵,這給他帶來了很大的限制。Map的出現,就是讓各類類型的值均可以看成鍵。Map提供的是 「值-值」的對應。
const map = new Map([
['name', '張三'],
['title', 'Author']
]);
map.size // 2
map.has('name') // true
map.get('name') // "張三"
map.has('title') // true
map.get('title') // "Author"
複製代碼
注意:Set 和 Map 均可以用來生成新的Map,若是對同一個鍵屢次賦值,那麼前面的將被後面的值覆蓋。另外只有對同一個對象的引用,Map結構纔將其視爲同一個鍵。另外一樣的兩個實例,在Map中將被視爲兩個鍵。
**總結:**綜上所述,Map的鍵實際上跟內存地址綁定的,只要內存地址不同,就視爲兩個鍵。這樣就能夠解決同名屬性碰撞的問題。若是咱們擴展別人庫的時候,若是使用對象最爲鍵名,就不用擔憂本身的屬性與原做者屬性衝突。
若是Map的鍵是一個簡單類型的數值,則只要兩個值嚴格相等,Map將其視爲一個鍵,0 和 -0 是一個鍵,true 和 'true'則是兩個不一樣的鍵, undefined 和 null 也是兩個不一樣的鍵, 另外 NaN 在Map 中視爲同一個鍵
size 屬性返回Map結構的成員總數
const map = new Map()
map.set('foo', ture)
map.set('bar', false)
map.size // 2
複製代碼
set 方法設置鍵名 key 對應的鍵值爲 value,而後返回整個 Map 結構。若是 key 已經有值,則鍵值會被更新,不然就新生成該鍵。
const m = new Map()
m.set('e', 6) // 鍵值是字符串
m.set(2, 's') // 鍵是數值
m.set(undefined, 'n') // 鍵是 undefined
// set方法返回的是當前的Map對象,所以能夠採用鏈式寫法
let map = new Map()
.set(1, 'a')
.set(2, 'b')
.set(3, 'c')
複製代碼
get 方法讀取 key 對應的鍵值,若是找不到key就返回 undefined
const m = new Map();
m.set('c', 124)
m.get('c') // 124
複製代碼
返回一個布爾值,用來表示某個鍵是否在當前 Map 對象中
let map = new Map()
.set(1, 'a')
.set(2, 'b')
.set(3, 'c')
map.has(1) // true
map.has(4) // false
複製代碼
delete方法刪除某個鍵,返回 true,若是刪除失敗,則返回 false
let map = new Map()
.set(1, 'a')
.set(2, 'b')
.set(3, 'c')
map.delete(1) // true
map.delete(4) // false
複製代碼
clear 方法清除全部成員,沒有返回值
let map = new Map()
.set(1, 'a')
.set(2, 'b')
.set(3, 'c')
map.size // 3
map.clear()
map.size // 0
複製代碼
注意:Map的遍歷順序就是插入順序。
Map 結構轉爲數組結構,比較快速的方法是使用擴展運算符(...),另外Map能夠經過 forEach 能夠實現遍歷。
const map = new Map([
[1, 'one'],
[2, 'two'],
[3, 'three'],
]);
[...map.keys()]
// [1, 2, 3]
[...map.values()]
// ['one', 'two', 'three']
[...map.entries()]
// [[1,'one'], [2, 'two'], [3, 'three']]
[...map]
// [[1,'one'], [2, 'two'], [3, 'three']]
複製代碼
經過擴展運算符(...)
將數組 傳入 Map構造函數,就能夠轉爲Map
new Map([
[true, 7],
[{foo: 3}, ['abc']]
])
複製代碼
若是Map的鍵都是字符串,它能夠無損地轉爲對象,若是有非字符串的鍵名,那麼這個鍵名會被轉成字符串,再做爲對象的鍵名。
Map轉爲JSON要區分兩種狀況。一種狀況是,Map 的鍵名都是字符串,這時能夠選擇轉爲對象JSON。另一種狀況是,Map 的鍵名有非字符串,這時能夠選擇轉爲數組JSON
JSON轉爲Map,正常狀況下,全部鍵名都是字符串。可是,有一種特殊狀況,整個JSON就是一個數組,且每一個數組成員自己,又是一個有兩個成員的數組。這時,它能夠一一對應地轉爲Map.
WeakMap 結構與 Map 結構相似,也是用於生成鍵值對的集合
WeakMap 和 Map 的區別
1. WeakMap只接受對象做爲鍵名(null除外),不接受其餘類型的值做爲鍵名。
2. WeakMap的鍵名所指向的對象,不計入垃圾回收機制。
複製代碼
若是 咱們想在某個對象上面存放以未數據,可是會造成對於這個對象的引用,若是咱們不須要這兩個對象,就必須手動刪除,不然垃圾回收機制就不會釋放佔用的內存。
WeakMap 就是爲了解決這個問題而誕生,它的鍵名所引用的對象都是弱引用,即垃圾回收機制不將該引用考慮在內。所以,只要所引用的對象的其餘引用被清除,垃圾回收機制就會釋放該對象所佔用的內存,也就是說一旦再也不須要,WeakMap裏面的鍵名對象和所對應的鍵值對會自動消失,不用手動刪除。
注意: WeakMap弱引用的只是鍵名,而不是鍵值。鍵值依然是正常引用。
WeakMap 與 Map 在 API的區別主要有兩個,一是沒有遍歷操做(沒有keys,values,entries),也沒有size屬性。由於沒有辦法列出全部鍵名,某個鍵名是否存在徹底不可預測,跟垃圾回收機制是否運行相關。這一刻能夠取到鍵名,下一個垃圾回收機制忽然運行了,這個鍵名就沒有了。爲了防止不肯定性,就統一規定不能取到鍵名。二是沒法狀況,即不支持 clear 方法。所以 WeakMap 有四個方法: get()、set()、has()、delete()
const wm = new WeakMap();
// size、forEach、clear 方法都不存在
wm.size // undefined
wm.forEach // undefined
wm.clear // undefined
複製代碼
歡迎關注 公衆號【小夭同窗】
重學js系列
ES6入門系列
Git教程