set(集合)和map(字典)這兩種數據結構的應用場景在於
數據重組
和數據存儲
javascript
ES6 新增的一種新的數據結構,相似於數組,但成員是
惟一且無序
的,沒有重複
的值(Set 對象容許你儲存任何類型的惟一值,不管是原始值
或者是對象引用
)java
const s = new Set()
[1, 2, 3, 4, 3, 2, 1].forEach(x => s.add(x))
for (let i of s) {
console.log(i) // 1 2 3 4
}
// 去重數組的重複對象
let arr = [1, 2, 3, 2, 1, 1]
[... new Set(arr)] // [1, 2, 3]
複製代碼
不會發生類型轉換
,因此5
和"5"
是兩個不一樣的值===
),主要的區別是NaN
等於自身,而精確相等運算符認爲NaN
不等於自身let set = new Set();
let a = NaN;
let b = NaN;
set.add(a);
set.add(b);
set // Set {NaN}
let set1 = new Set()
set1.add(5)
set1.add('5')
console.log([...set1]) // [5, "5"]
複製代碼
屬性和方法算法
let set = new Set()
set.add(1).add(2).add(1)
set.size // 2
set.has(1) // true
set.has(3) // false
set.delete(1)
set.has(1) // false
複製代碼
Array.from 方法能夠將 Set 結構轉爲數組json
const items = new Set([1, 2, 3, 2])
const array = Array.from(items)
console.log(array) // [1, 2, 3]
// 或
const arr = [...items]
console.log(arr) // [1, 2, 3]
複製代碼
遍歷方法(遍歷順序爲插入順序)數組
keys():返回一個包含集合中全部鍵的迭代器(由於set加入的值沒有key,因此返回的是value值
)數據結構
values():返回一個包含集合中全部值得迭代器函數
entries():返回一個包含Set對象中全部元素得鍵值對迭代器ui
forEach(callbackFn, thisArg):用於對集合成員執行callbackFn操做,若是提供了 thisArg 參數,回調中的this會是這個參數,沒有返回值this
let set = new Set([1, 2, 3])
console.log(set.keys()) // SetIterator {1, 2, 3}
console.log(set.values()) // SetIterator {1, 2, 3}
console.log(set.entries()) // SetIterator {1, 2, 3}
for (let item of set.keys()) {
console.log(item);
} // 1 2 3
for (let item of set.entries()) {
console.log(item);
} // [1, 1] [2, 2] [3, 3]
set.forEach((value, key) => {
console.log(key + ' : ' + value)
}) // 1 : 1 2 : 2 3 : 3
console.log([...set]) // [1, 2, 3]
複製代碼
Set 可默認遍歷,默認迭代器生成函數是 values() 方法,可使用map、filter等方法spa
Set.prototype[Symbol.iterator] === Set.prototype.values // true
let set = new Set([1, 2, 3])
set = new Set([...set].map(item => item * 2))
console.log([...set]) // [2, 4, 6]
set = new Set([...set].filter(item => (item >= 4)))
console.log([...set]) //[4, 6]
複製代碼
Set 很容易實現交集(Intersect)、並集(Union)、差集(Difference)
let set1 = new Set([1, 2, 3])
let set2 = new Set([4, 3, 2])
let intersect = new Set([...set1].filter(value => set2.has(value)))
let union = new Set([...set1, ...set2])
let difference = new Set([...set1].filter(value => !set2.has(value)))
console.log(intersect) // Set {2, 3}
console.log(union) // Set {1, 2, 3, 4}
console.log(difference) // Set {1}
複製代碼
WeakSet 對象容許你將弱引用對象儲存在一個集合中
WeakSet 與 Set 的區別:
WeakSet 只能儲存對象引用
,不能存放值
,而 Set 對象均可以
WeakSet 對象中儲存的對象值都是被弱引用的,即垃圾回收機制不考慮 WeakSet 對該對象的應用,若是沒有其餘的變量或屬性引用這個對象值,則這個對象將會被垃圾回收掉(不考慮該對象還存在於 WeakSet 中),因此,WeakSet 對象裏有多少個成員元素,取決於垃圾回收機制有沒有運行,運行先後成員個數可能不一致,遍歷結束以後,有的成員可能取不到了(被垃圾回收了),WeakSet 對象是沒法被遍歷的(ES6 規定 WeakSet 不可遍歷),也沒有辦法拿到它包含的全部元素
屬性和方法的區別:沒有size屬性和clear方法
var ws = new WeakSet()
var obj = {}
var foo = {}
ws.add(window)
ws.add(obj)
ws.has(window) // true
ws.has(foo) // false
ws.delete(window) // true
ws.has(window) // false
複製代碼
集合 與 字典 的區別:
const m = new Map()
const o = {p: 'haha'}
m.set(o, 'content')
m.get(o) // content
m.has(o) // true
m.delete(o) // true
m.has(o) // false
複製代碼
任何具備 Iterator 接口、且每一個成員都是一個雙元素的數組的數據結構均可以看成Map
構造函數的參數
const set = new Set([
['foo', 1],
['bar', 2]
]);
const m1 = new Map(set);
m1.get('foo') // 1
const m2 = new Map([['baz', 3]]);
const m3 = new Map(m2);
m3.get('baz') // 3
複製代碼
只有對同一個對象的引用,Map 結構纔將其視爲同一個鍵。這一點要很是當心
const map = new Map();
map.set(['a'], 555);
map.get(['a']) // undefined
複製代碼
上面代碼的set
和get
方法,表面是針對同一個鍵,但實際上這是兩個值,內存地址是不同的,所以get
方法沒法讀取該鍵,返回undefined
。
由上可知,Map 的鍵其實是跟內存地址綁定的,只要內存地址不同,就視爲兩個鍵。這就解決了同名屬性碰撞(clash)的問題,咱們擴展別人的庫的時候,若是使用對象做爲鍵名,就不用擔憂本身的屬性與原做者的屬性同名。
若是 Map 的鍵是一個簡單類型的值(數字、字符串、布爾值),則只要兩個值嚴格相等,Map 將其視爲一個鍵,好比0
和-0
就是一個鍵,布爾值true
和字符串true
則是兩個不一樣的鍵。另外,undefined
和null
也是兩個不一樣的鍵。雖然NaN
不嚴格相等於自身,但 Map 將其視爲同一個鍵
let map = new Map();
map.set(-0, 123);
map.get(+0) // 123
map.set(true, 1);
map.set('true', 2);
map.get(true) // 1
map.set(undefined, 3);
map.set(null, 4);
map.get(undefined) // 3
map.set(NaN, 123);
map.get(NaN) // 123
複製代碼
屬性和方法
size:返回字典中所包含的元素個數
const map = new Map([
['name', 'An'],
['des', 'JS']
]);
map.size // 2
複製代碼
set(key, value):向字典中添加新元素
get(key):經過鍵查找特定的數值並返回
has(key):判斷字典中是否存在鍵key
delete(key):經過鍵 key 從字典中移除對應的數據
clear():將這個字典中的全部元素刪除
遍歷方法
Map 結構的默認遍歷器接口(Symbol.iterator
屬性),就是entries
方法。
map[Symbol.iterator] === map.entries
// true
複製代碼
const reporter = {
report: function(key, value) {
console.log("Key: %s, Value: %s", key, value);
}
};
let map = new Map([
['name', 'An'],
['des', 'JS']
])
map.forEach(function(value, key, map) {
this.report(key, value);
}, reporter);
// Key: name, Value: An
// Key: des, Value: JS
複製代碼
與其餘數據結構的相互轉換
Map 轉 Array
const map = new Map([[1, 1], [2, 2], [3, 3]])
console.log([...map]) // [[1, 1], [2, 2], [3, 3]]
複製代碼
Array 轉 Map
const map = new Map([[1, 1], [2, 2], [3, 3]])
console.log(map) // Map {1 => 1, 2 => 2, 3 => 3}
複製代碼
Map 轉 Object
function mapToObj(map) {
let obj = Object.create(null)
for (let [key, value] of map) {
obj[key] = value
}
return obj
}
const map = new Map().set('name', 'An').set('des', 'JS')
mapToObj(map) // {name: "An", des: "JS"}
複製代碼
Object 轉 Map
function objToMap(obj) {
let map = new Map()
for (let key of Object.keys(obj)) {
map.set(key, obj[key])
}
return map
}
objToMap({'name': 'An', 'des': 'JS'}) // Map {"name" => "An", "des" => "JS"}
複製代碼
Map 轉 JSON
function mapToJson(map) {
return JSON.stringify([...map])
}
let map = new Map().set('name', 'An').set('des', 'JS')
mapToJson(map) // [["name","An"],["des","JS"]]
複製代碼
JSON 轉 Map
function jsonToStrMap(jsonStr) {
return objToMap(JSON.parse(jsonStr));
}
jsonToStrMap('{"name": "An", "des": "JS"}') // Map {"name" => "An", "des" => "JS"}
複製代碼
WeakMap 對象是一組鍵值對的集合,其中的鍵是弱引用對象,而值能夠是任意
注意,WeakMap 弱引用的只是鍵名,而不是鍵值。鍵值依然是正常引用。
WeakMap 中,每一個鍵對本身所引用對象的引用都是弱引用,在沒有其餘引用和該鍵引用同一對象,這個對象將會被垃圾回收(相應的key則變成無效的),因此,WeakMap 的 key 是不可枚舉的。
屬性和方法的區別是:沒有size屬性和clear方法