Set WeakSet Map WeakMap

425 阅读4分钟

这是我参与8月更文挑战的第5天,活动详情查看:8月更文挑战

前言

Set 和 Map 是 es6 的新的数据结构,学习和掌握它们有助于利用其特性更优雅的处理数据

Set

Set 的成员是唯一的。根据这个特性可用数据的去重工作,但是两个对象的值总是不想等的,源自于对象的引用不相等

const arr = [2, 3, 5, 4, 5];
const set2 = new Set(arr)
// [2, 3, 5, 4]

操作数据

  1. size: 返回 Set 的大小
  2. add(value): 添加某个值,会返回 Set 结构本身,故可以使用链式调用
  3. delete(value): 删除某个值,返回一个是否删除成功的布尔值
  4. has(value): 判断 value 是否存在于 Set,返回一个是否存在的布尔值,
  5. clear(): 清除所有成员,返回 undefined
const set1 = new Set([])
set1.size // 0
set1.add(1).add(2) // Set(4) {1, 2}
set1.has(1) // true
set1.delete(2) // true
set1.has(2) // false
set1.size // 1
set1.clear() // undefined
set1 // Set(0) {}

遍历数据

  1. keys(): 遍历键名
  2. values(): 遍历键值
  3. entries(): 遍历键值对
  4. forEach(): 类似数组的 forEach
  5. ...: 扩展运算符,将数据转化为数组

Set 具有 iterable,所以会有 keys() values() entries(),便可以使用 for...of 遍历。Set 的数据结构中键名和键值为同一个值,keys() 和 values() 结果一致。

Set 的原型上绑定的 [Symbol.iterator] 是 values(),亦可直接遍历

const set1 = new Set(['r', 'g', 'b'])
for (const key of set1.keys()) {
    console.log(key)
}
// r  g  b

for (const value of set1.values()) {
    console.log(value)
}
// r  g  b

for (const [key, value] of set1.entries()) {
    console.log(key, value)
}
// r r  g g  b b

for (const value of set1) {
    console.log(value)
}
// r  g  b

console.log(...set1)
// r g b

console.log(Array.from(set1))
// ['r', 'g', 'b']

WeakSet

WeakSet 和 Set 的用法类似,但是有一些限制,可以说 WeakSet 是 Set 的子集

  1. WeakSet 的成员只能是对象或者具有 Iterable 接口的对象,否则会报错
  2. WeakSet 中的对象都是弱引用,不会计入垃圾回收机制,故不可遍历

方法

  1. add(value): 添加 value,返回自身,也可链式调用
  2. delete(value): 删除 value,返回是否删除成功的布尔值
  3. has(value): 判断 value 是否存在,返回布尔值
const ws = new WeakSet()
const obj = {}
ws.add(obj).add([])
ws.delete(obj) // true
ws.has(obj) // false
ws.size // undefined

Map

Map 是一种值-值的形式,解决了 Object 只能使用字符串做为键值的限制

const arr = [
    ["name", "san"],
    ["age", 1],
  ];
const map = new Map(arr);
  1. 同一个键名的赋值依据最新的为准
  2. 未知的键返回 undefined
  3. 对象的引用地址决定是否为同一值
  4. 不同于 === 判断逻辑,undefined 和 null 不是同一个键,NaN 视为同一个键

操作方法

  1. size: 返回 Map 结构的个数
  2. set(key, value): 键值对形式添加,然后返回整个 Map 结构;可使用链式结构
  3. get(key): 返回键名 key 对应的键值,否则返回 undefined
  4. has(key): 判断键名 key 是否存在于数据中,返回存在与否的布尔值
  5. delete(key): 删除键名为 key 的数据。成功删除结果的布尔值
  6. clear(): 清除所有成员,返回 undefined
const arr1 = [[1, 2], [NaN, 1]]
const map1 = new Map(arr1)
map1.size // 2
map1.set(1, 2).set(NaN, 2)
map1.get(NaN) // 2
map1.delete(1) // true
map1.clear() // undefined

遍历数据

  1. keys() 遍历键名
  2. values() 遍历键值
  3. entries() 遍历键值对
  4. forEach() 类似数组的 forEach

Map 也是 Iterable,自然有着 keys() values() 和 entries()。

const map1 = new Map()
map1.set('a', 'one')
map1.set('b', 'two')

for (const key of map1.keys()) {
    console.log(key)
}
// a b

for (const value of map1) {
    console.log(value)
}
// one two

for (const [key, value] of map1) {
    console.log(key, value)
}
// a one  b two

for (const item of map1) {
    console.log(item)
}
// ['a', 'one'] ['b', 'two']

console.log(...map1)
// ['a', 'one'] ['b', 'two']

console.log(Array.from(map1))
// [['a', 'one'], ['b', 'two']]

WeakMap

同理,WeakMap 可以看成 Map 的子集

  1. WeakMap 只接受对象作为键名(null 除外 typeof null === 'object'),或者 满足Iteractor
  2. WeakMap 的键名所指向的对象

方法

  1. get(key): 返回 key 对应的键值,没有返回 undefined
  2. set(key, value): 设置值,返回本身,可链式调用
  3. has(value): 判断是否存在 value,返回布尔值
  4. delete(value): 删除 value,返回布尔值
const wm = new WeakMap()
const obj1 = {}
const arr1 = []
const map1 = new Map()

wm.set(obj1, 1).set(arr1, 2).set(map1, 3)
console.log(wm.get(map1)) // 3
console.log(wm.has(obj1)) // true
console.log(wm.delete(arr1)) // true

总结

  1. 这四个都是 Iterable 可迭代对象,也都是构造函数,设置数据的方法都可以链式调用
  2. Set Map 可以从操作和遍历两个方面去掌握
  3. WeakSet WeakMap 的弱引用适用于存储临时数据
  4. 要注意对象数组这类引用的数据,它们真正使用的是引用的地址。可以考虑结合浅拷贝和深拷贝的原理理解这部分