Set 、 Map为ES6新增的数据结构。
ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。
Set 本身是一个构造函数,用来生成 Set 数据结构。
// 声明方式
let s = new Set()
console.log(s)
//唯一的
let s = new Set([1, 2, 3, 2])
// 添加新的值
s.add('kaka').add('Dorothy') // 支持链式操作
// s.delete(2) // 删除2
// s.clear() // 清空
console.log(s.has('kaka')) //true,判断是否包含某个值
console.log(s) // 1 2 3 kaka Dorothy
console.log(s.size) // 输出Set的长度
s.forEach(item => console.log(item))
for (let item of s) {
console.log(item)
}
for (let item of s.keys()) {
console.log(item)
}
for (let item of s.values()) {
console.log(item)
}
for (let item of s.entries()) {
console.log(item[0], item[1])
//1 1
//2 2
//3 3
//kaka kaka
//Dorothy Dorothy
}
Set相当于也有key:value,只不过它的key和value是相同的。
let arr = [1, 2, 3, 4, 2, 3]
let s = new Set(arr)
console.log(s)
let arr1 = [1, 2, 3, 4]
let arr2 = [2, 3, 4, 5, 6]
let s = new Set([...arr1, ...arr2])
console.log(s)
// {1, 2, 3, 4, 5, 6}
// set->array
console.log([...s])
console.log(Array.from(s))
//[1, 2, 3, 4, 5, 6]
let s1 = new Set(arr1)
let s2 = new Set(arr2)
let result = new Set(arr1.filter(item => s2.has(item)))
//{2, 3, 4}
console.log(Array.from(result))
//[2, 3, 4]
let arr3 = new Set(arr1.filter(item => !s2.has(item)))
let arr4 = new Set(arr2.filter(item => !s1.has(item)))
console.log(arr3)
//{1}
console.log(arr4)
//{5, 6}
console.log([...arr3, ...arr4])
//[1, 5, 6]
WeakSet只能够存储对象(与Set的区别1),数字、字符串等原始数据对象不能够放进去。WeakSet不能够遍历(区别2)。
let ws = new WeakSet()
const obj1 = {
name: 'kaka'
}
const obj2 = {
age: 5
}
ws.add(obj1)
ws.add(obj2)
// 删除对象
ws.delete(obj1)
console.log(ws)
//仅剩obj2
console.log(ws.has(obj2))
//true
ws.forEach(item => console.log(item))
//报错
垃圾回收机制:GC +1 +1,只要GC后面的值不为0,则不会被回收,所以可能会有内存泄漏的风险。
WeakSet 的对象是弱引用,它不会被计入垃圾回收机制(区别3),所以不管它是否还有引用,当前使用完之后便回收了,可用于临时存放对象。
JavaScript 的对象(Object),本质上是键值对的集合(Hash 结构),但是传统上只能用字符串当作键。这给它的使用带来了很大的限制。为了解决这个问题,ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以 当作键。也就是说,Object 结构提供了“字符串-值”的对应,Map 结构提供了“值-值”的对应,是一种更完善的 Hash 结构实现。如果需要“键值 对”的数据结构,Map 比 Object 更合适。
let m = new Map()
let obj = {
name: 'kaka'
}
// set添加新的值 key:value
m.set(obj, 'es')
console.log(m)
// 输出整个Map
// get获取值
console.log(m.get(obj)) // es
// 删除
m.delete(obj)
// 判断是否包含当前这个key对应的值
console.log(m.has(obj))
将数组作为参数:
// 将数组作为参数
let map = new Map([
['name', 'kaka'],
['age', 5]
])
console.log(map.size)
// 2
console.log(map.has('name')) // true
console.log(map.get('age')) // 5
map.set('name', 'wengweng') // "name" => "wengweng"
map.delete('name') // 删除
map.clear() // 清空
console.log(map)
与Set的区别是,Set的key和value是相同的,而Map的不同。
//遍历
map.forEach((value, key) => console.log(value, key))
for(let [key, value] of map){
console.log(key, value)
}
for(let key of map.keys()){
console.log(key)
}
for(let value of map.values()){
console.log(value)
}
for(let [key, value] of map.entries()){
console.log(key, value)
}
与Object比较:
① Map判断是否包含某个属性时可直接调用.has(),而Object需要循环遍历才能够判断,所以Map的api更加灵活。
② Map的key更多样。
③ Map可直接通过.size()来获取键值对的个数,而Object仍需要循环。
④ Object含有自己的原型,原型链上的名字与自己定义的键名可能会冲突。
使用Object的场景都可考虑使用Map。
WeakMap与Map的结构相似,不同点在于:WeakMap的键名(key)仅支持引用数据类型(对象、数组、函数),且WeakMap不支持遍历,也是一种弱引用,不会被计入垃圾回收机制。
let wm = new WeakMap()
wm.set([1], 2)
wm.set({
name: 'kaka'
}, 'es')
// WeakMap不支持clear清空
wm.clear() // 报错
// WeakMap不支持size方法(因为也涉及到遍历)
console.log(wm.size) // undefined
// 应用场景
let wm = new WeakMap()
let elem = document.getElementsByTagName('h1')
wm.set(elem, 'info')
console.log(wm.get(elem))
Set相对于数组(Array)
Map相对于对象(Object)