Set集合是一种无重复元素列表,Map集合含多组键值对。在es5中,有些开发者通过非数组对象实现了类似功能。如今,Set集合 和 Map 集合被作为标准添加到es6中。
Set 集合
Set类型是一种有序列表,其中含有相互独立的非重复值,通过Set集合可以快速访问其中的数据,有效的追踪各种离散值。
创建Set集合并添加元素
let set = new Set()
set.add(5)
set.add('5')
console.log(set.size) // 2
如果多次添加重复的值,则会被忽略:
let set = new Set()
set.add(5)
set.add('5')
set.add('5')
set.add('5')
set.add('5')
console.log(set.size) // 2
还可以用来给数组去重:
let set = new Set([1, 1, 1, 2, 2, 2, 3, 3, 3])
console.log(Array.from(set)) // [ 1, 2, 3 ]
通过has方法检测是否存在某个值:
let set = new Set()
set.add(5)
console.log(set.has("5")) // false
还可以通过delete移除某个元素:
let set = new Set()
set.add(5)
set.add('5')
set.delete('5')
console.log(set.has("5")) // false
可以通过 clear 方法清空集合:
let set = new Set()
set.add(5)
set.add('5')
set.clear()
console.log(set.size) // 0
遍历Set集合:
let set = new Set()
set.add(5)
set.add(10)
set.forEach((value, key, ownerSet) => {
console.log(value)
console.log(key)
console.log(ownerSet === set)
console.log('=============')
})
// 5
// 5
// true
// =============
// 10
// 10
// true
// =============
Set 集合转数组:
let set = new Set([1, 1, 1, 2, 2, 2, 3, 3, 3])
console.log([...set]) // [ 1, 2, 3 ]
console.log(Array.from(set)) // [ 1, 2, 3 ]
WeakSet 集合
Set集合是强引用,我们看个例子:
let set = new Set()
let obj = {}
set.add(obj)
obj = null
console.log(set.size) // 1
我们将对象obj创建后,添加到Set集合,然后销毁对象obj,但是Set集合中仍然存在obj,这就是强引用,有时候处理不当,容易引起内存泄漏。
为了解决这个问题,es6又推出了 WeakSet集合,也就是弱引用的Set集合。
WeakSet集合也支持 add()、has()、delete() 方法。
与Set集合的区别如下:
- add()、has()、delete() 方法不支持传入非对象数据。
- 不可迭代,不可被用于 for-of循环。
- 不暴露迭代器,例如 keys() 和 values()。
- 不支持forEach()方法。
- 不支持size属性。
所以,它只适合正确处理内存中的数据,只能跟踪数据。
Map 集合
Map集合是一种含多组键值对的有序列表,键值名和对应值支持所有数据类型。键值的等价性判断是通过调用Object.is()方法实现,所以 1 和 '1' 会被判定为两种类型。所以和对象不同,对象会被强制转换为字符串类型。
向Map集合添加和获取元素:
let map = new Map()
map.set('title', 'hello es6')
map.set('year', '2022')
console.log(map.get('title')) // hello es6
console.log(map.get('year')) // 2022
let key1 = {}
let key2 = {}
map.set(key1, 'set key1')
map.set(key2, 'set key2')
console.log(map.get(key1)) // set key1
console.log(map.get(key2)) // set key2
Map集合的方法:
- has(key) 检测指定键名在 Map 集合是否存在。
- delete(key) 从Map集合删除指定键名对应的值。
- clear() 移除Map() 集合中的所有键值对。
属性:size
let map = new Map()
map.set('title', 'hello es6')
map.set('year', '2022')
console.log(map.get('title')) // hello es6
console.log(map.has('title')) // true
map.delete('year')
console.log(map.size) // 1
map.clear()
console.log(map.size) // 0
Map也可以和Set一样通过构造函数初始化:
let map = new Map([['title', 'hello es6'], ['year', '2022']])
console.log(map.get('title')) // hello es6
console.log(map.has('title')) // true
Map的forEach遍历:
let map = new Map([['title', 'hello es6'], ['year', '2022']])
map.forEach((value, key, ownerMap) => {
console.log(value)
console.log(key)
console.log(ownerMap)
console.log('========')
})
// hello es6
// title
// Map { 'title' => 'hello es6', 'year' => '2022' }
// ========
// 2022
// year
// Map { 'title' => 'hello es6', 'year' => '2022' }
// ========
Weak Map集合
WeakMap 是弱引用的 Map集合。也用于存储对象的弱引用。WeakMap 对象的键名必须是一个对象。
WeakMap 对象一般用于保存Web页面的DOM元素,因为它可以在DOM元素消失时,自动销毁集合中的相关对象,避免内存泄漏。
let map = new WeakMap()
let element = document.querySelector('.element')
map.set(element, 'Original')
let value = map.get(element)
console.log(value) // Original
// 移除element元素
element.parentNode.removeChild(element)
element = null
// 此时 WeakMap 集合为空
WeakMap 支持的方法:
-
支持has()
-
支持delete()
-
不支持键值枚举,不支持clear()
WeakMap 的其它用法:
它的自动销毁特性,无疑可以用来存储私有属性,比用闭包来创建可以有效的避免内存泄露的风险。
let Person = (function () {
let privateData = new WeakMap()
function Person (name) {
privateData.set(this, { name, name })
}
Person.prototype.getName = function () {
return privateData.get(this).name
}
return Person
})()
const person = new Person('李四')
console.log(person.name) // undefined
console.log(person.getName()) // 李四