《JavaScript红宝书(第四版)》第6章
6.3 定型数组
目前项目中没有对其进行应用,暂且跳过细节
6.4 Map
6.4.1 基本API
//注意初始化,new Map()后的[]是双层数组,否则报错
let map1 = new Map([['zhangsan', 23],['lisi',34]])
map1.set('wangwu', 28) //Map(3) {"zhangsan" => 23, "lisi" => 34, "wangwu" => 28}
map1.has('lisi') //true
map1.has('lili') //false
map1.get('wangwu') //28
map1.delete("lisi") //true
map1 //Map(2) {"zhangsan" => 23, "wangwu" => 28}
map1.clear() //undefined
map1 //Map(0) {}
Map与Object不同,Object的key只能是数值、字符串或者符号。Map的key可以是任意类型,如function, object, Symbol
6.4.2 顺序与迭代
与Object不同,Map会维护键值对插入的顺序,可以根据该顺序进行迭代操作
- 使用
entries或者Symbol.iterator
迭代:
let map1 = new Map([['zhangsan', 23],['lisi',34]])
for(let pair of map1.entries()){
console.log(pair)
}
//(2) ["zhangsan", 23]
//(2) ["lisi", 34]
for(let pair of map1[Symbol.iterator]()){
console.log(pair)
}
//(2) ["zhangsan", 23]
//(2) ["lisi", 34]
- 使用forEach, 这样语句更简洁
map1.forEach((key, val) => console.log(`key: ${key}, value: ${val}`))
//key: 23, value: zhangsan
//key: 34, value: lisi
map1.forEach(val => console.log(val))
//23
//34
- 使用解构直接转换为Array
const arr2 = [...map1]
arr2
//(2) ["zhangsan", 23]
//(2) ["lisi", 34]
- 访问
xxx.keys(), xxx.values()
同样生效,与Object类似 - 迭代中,修改key值后,key的引用不会被修改,该场景暂时未遇到。
6.4.3 Object VS. Map
对比项目 | 胜出者 | |
内存占用 | Map | |
插入速度 | Map略胜一筹 | |
查找速度 | 差异极小,大量查找偏向于Object | |
删除性能 | Map胜出,由于Object删除后会继续留下该key,将value改为null或undefined而饱受诟病 |
6.5 WeakMap(了解,尚未深入研究)
- WeakMap相比于Map的一些特性
- key只能是Object,value无限制
- 不能遍历key
- 只有
get, set, has, delete
方法,没有keys, values, entries
, 没有size属性,没有clear
方法
- 使用场景
MDN: 如果你想要往对象上添加数据,而又不想干扰垃圾回收机制,可以使用WeakMap
- 比如DOM节点元数据,数据缓存,私有变量等
6.6 Set
- 基础API
【注意】, Set的key与value相同
const s = new Set()
s.add('pink').add('yellow') //Set(2) {"pink", "yellow"}
s.has('pink') //true
s.has('purple') //false
//keys与values,得到的结果相同
const arr = s.keys()
const arr1 = s.values()
arr //SetIterator {"pink", "yellow"}
arr1 //SetIterator {"pink", "yellow"}
//set中的元素,可以添加任何类型
let func = function() {}
s.add(func) //Set(3) {"pink", "yellow", ƒ}
//重复添加,是不起作用的,自动去重
s.add('pink') //Set(3) {"pink", "yellow", ƒ}
//delete操作,返回布尔值
s.delete('yellow') //true
s.delete('black') //false
- 顺序与迭代
与Map特性相同,Set也会维护插入的顺序,可以根据该顺序进行迭代操作
- 迭代的方式,与Map类似,
keys, values, entries, forEach
- 由于key与value相同,所以使用entries进行迭代时,得到的是[value, value]这样的结构
6.7 正式集合操作
可以定义多个集合的并集,交集,差集等操作,如果对于array也有类似的需求,可以先转换为Set再进行操作,也很方便快捷,这里复制代码,以后作为工具类使用即可
class XSet extends Set {
union(...sets) {
return XSet.union(this, ...sets)
}
intersection(...sets) {
return XSet.intersection(this, ...sets)
}
difference(set) {
return XSet.difference(this, set)
}
symmetricDifference(set) {
return XSet.symmetricDifference(this, set)
}
cartesianProduct(set) {
return XSet.cartesianProduct(this, set)
}
powerSet() {
return XSet.powerSet(this)
}
// 返回两个或更多集合的并集
static union(a, ...bSets) {
const unionSet = new XSet(a)
for (const b of bSets) {
for (const bValue of b) {
unionSet.add(bValue)
}
}
return unionSet
}
// 返回两个或更多集合的交集
static intersection(a, ...bSets) {
const intersectionSet = new XSet(a)
for (const aValue of intersectionSet) {
for (const b of bSets) {
if (!b.has(aValue)) {
intersectionSet.delete(aValue)
}
}
}
return intersectionSet
}
// 返回两个集合的差集
static difference(a, b) {
const differenceSet = new XSet(a)
for (const bValue of b) {
if (a.has(bValue)) {
differenceSet.delete(bValue)
}
}
return differenceSet
}
// 返回两个集合的对称差集
static symmetricDifference(a, b) {
// 按照定义,对称差集可以表达为
return a.union(b).difference(a.intersection(b))
}
// 返回两个集合(数组对形式)的笛卡儿积
// 必须返回数组集合,因为笛卡儿积可能包含相同值的对
static cartesianProduct(a, b) {
const cartesianProductSet = new XSet()
for (const aValue of a) {
for (const bValue of b) {
cartesianProductSet.add([aValue, bValue])
}
}
return cartesianProductSet
}
// 返回一个集合的幂集
static powerSet(a) {
const powerSet = new XSet().add(new XSet())
for (const aValue of a) {
for (const set of new XSet(powerSet)) {
powerSet.add(new XSet(set).add(aValue))
}
}
return powerSet
}
}
6.8 WeakSet
类似于WeakMap,它的作用也是偏重于垃圾回收机制,在vue的源码中应该有所使用,尤其是在进行DOM节点打标签时,如果元素从DOM树中删除了,那么WeakSet就会回收元素的内层,而Set则不会。