这是我参与8月更文挑战的第5天,活动详情查看:8月更文挑战
前言
Set 和 Map 是 es6 的新的数据结构,学习和掌握它们有助于利用其特性更优雅的处理数据
Set
Set 的成员是唯一的。根据这个特性可用数据的去重工作,但是两个对象的值总是不想等的,源自于对象的引用不相等
const arr = [2, 3, 5, 4, 5];
const set2 = new Set(arr)
// [2, 3, 5, 4]
操作数据
- size: 返回 Set 的大小
- add(value): 添加某个值,会返回 Set 结构本身,故可以使用链式调用
- delete(value): 删除某个值,返回一个是否删除成功的布尔值
- has(value): 判断 value 是否存在于 Set,返回一个是否存在的布尔值,
- 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) {}
遍历数据
- keys(): 遍历键名
- values(): 遍历键值
- entries(): 遍历键值对
- forEach(): 类似数组的 forEach
- ...: 扩展运算符,将数据转化为数组
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 的子集
- WeakSet 的成员只能是对象或者具有 Iterable 接口的对象,否则会报错
- WeakSet 中的对象都是弱引用,不会计入垃圾回收机制,故不可遍历
方法
- add(value): 添加 value,返回自身,也可链式调用
- delete(value): 删除 value,返回是否删除成功的布尔值
- 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);
- 同一个键名的赋值依据最新的为准
- 未知的键返回 undefined
- 对象的引用地址决定是否为同一值
- 不同于 === 判断逻辑,undefined 和 null 不是同一个键,NaN 视为同一个键
操作方法
- size: 返回 Map 结构的个数
- set(key, value): 键值对形式添加,然后返回整个 Map 结构;可使用链式结构
- get(key): 返回键名 key 对应的键值,否则返回 undefined
- has(key): 判断键名 key 是否存在于数据中,返回存在与否的布尔值
- delete(key): 删除键名为 key 的数据。成功删除结果的布尔值
- 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
遍历数据
- keys() 遍历键名
- values() 遍历键值
- entries() 遍历键值对
- 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 的子集
- WeakMap 只接受对象作为键名(null 除外 typeof null === 'object'),或者 满足Iteractor
- WeakMap 的键名所指向的对象
方法
- get(key): 返回 key 对应的键值,没有返回 undefined
- set(key, value): 设置值,返回本身,可链式调用
- has(value): 判断是否存在 value,返回布尔值
- 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
总结
- 这四个都是 Iterable 可迭代对象,也都是构造函数,设置数据的方法都可以链式调用
- Set Map 可以从操作和遍历两个方面去掌握
- WeakSet WeakMap 的弱引用适用于存储临时数据
- 要注意对象数组这类引用的数据,它们真正使用的是引用的地址。可以考虑结合浅拷贝和深拷贝的原理理解这部分