《JavaScript: The Definitive Guide》【读犀牛书】- 第 11 章 集合和映射

114 阅读4分钟

【读犀牛书】是《JavaScript: The Definitive Guide》这本书个人学习笔记的汇总,目的是夯实前端 JS 基础,欢迎讨论!

🐧 前情提要

阅读本章节你会了解到以下内容:

  1. 理解集合、映射
  2. Set 类
  3. Map 类
  4. 知识扩展
  5. 小结

1. 理解集合、映射

之前提到了 JavaScript 中数组、对象比较基础且常用的概念,本章介绍 ES6 新增的两个类,分别是集合 Set 和映射 Map。对数组而言,这两者有其各自的作用,且在检查元素是否存在时,相比数组更加高效,查询速度更快。

  • 集合 Set: 表示一组值的集合
  • 映射 Map: 表示一组值到另一组值的关系,即键值映射

2. Set 类

集合是一组值,特点是无序集合、没有索引、无重复元素;而数组则是有序集合、可以通过索引访问元素、可以有重复的元素,这是两者的区别

(1)创建 Set 对象

Set 集合中的元素,不一定是数组,只要是可迭代的对象都可以

let s = new Set()
let s = new Set([1,2,4,7])
let s = new Set('phoebe')

(2)Set 对象的容量

let s = new Set([1,2,4,7])
s.size    // 4

(3) Set 对象的操作

add() 添加元素、delete() 删除元素、clear() 清空集合

  • add() 添加元素时,如果重复添加相同的元素,是不生效的,其 size 不变
  • delete() 删除元素时,如果集合中有该元素,则返回 true 删除成功;若没有该元素,则返回 false 删除失败
  • 添加和删除引用类型时,注意因为集合中判断元素是否相等是根据 === 判断的,所以尽管两个数组是相同的元素,但也会被判断为非重复元素 [1] === [1] // false 删除时也是类似的,若想删除一个数组元素,必须删除其数组的引用
let s = new Set([1,2,4,7])
s.add(6)      // [1,2,4,7,6]
s.add(6)      // [1,2,4,7,6]
s.delete(2)   // true
s.delete(3)   // false
s.clear()     // []

(4)Set 对象的检测

检测某个元素是否存在在集合中,可以使用 has() 方法;与数组中检测方法 includes() 相比,Set 集合的 has() 更加快速,随着集合中元素的数量越多,对比越明显

let s = new Set([1,2,4,7])
s.has(4)    // true
s.has(3)    // false

(5)Set 对象的遍历

因为 Set 对象是可迭代的,所以可以使用如下方法 for...of、forEach()、扩展运算符将集合转换成数组

let s = new Set([1,2,4,7])

for(let value of s) {
    console.log(value)    // 1 2 4 7
}

s.forEach((value) => {
    console.log(value)    // 1 2 4 7
})

let arr = [...s]
console.log(arr)    // [1,2,4,7]

3. Map 类

映射是一组键值关系;某种程度上,映射也类似数组,同样查询某个键关联的值时,比数组速度更快的

(1)创建 Map 对象

let m = new Map()
let m = new Map([ [x:1],[y:2] ])

(2)Map 对象的容量

let m = new Map([ [x:1],[y:2] ])
s.size    // 2

(3) Map 对象的操作

get() 获取元素、set() 添加/更新元素、delete() 删除元素、clear() 清空集合

let m = new Map()
m.set('x',1)    // Map(1) {'x' => 1}
m.set('y',2)    // Map(2) {'x' => 1, 'y' => 2}
m.get('x')      // 1
m.delete('x')   // true
m.clear()       // Map(0) {size: 0}

(4)Map 对象的检测

检测某个键是否存在于映射中,可以使用 has() 方法

let m = new Map([ [x:1],[y:2] ])
m.has(x)    // true
m.has(z)    // false

(5)Map 对象的遍历

因为 Map 对象是可迭代的,所以可以使用如下方法 for...of、forEach()、keys()、values()、entries()、解构赋值

let m = new Map([ ['x',1],['y',2] ])

for(let [key,value] of m) {
    console.log(key, value) // x 1  y 2
}

m.forEach((value, key) => {
    console.log(key, value)  // x 1 y 2
})

const keys = [...m.keys()]    // ['x', 'y']

const values = [...m.values()]    // [1, 2]

const entries = [...m.entries()]    // [['x',1],['y',2]]

[...m]    // [['x',1],['y',2]]
const [a,b] = [...m]
a   // ['x', 1]
b   // ['y', 2]

4. 知识扩展

WeakSet 弱集合、WeakMap 弱映射

(1)主要作用

实现对象标记存储在集合中,或对象和值的关系存储在映射中,而不导致内存泄漏,有垃圾收集机制

(2)特性

  • WeakSet() 值、WeakMap() 键只能是对象或数组,不能是原始值,因为原始值不受垃圾收集控制
  • WeakSet() 仅实现了 add()、has()、delete()
  • WeakMap() 仅实现了 get()、set()、has()、delete()
  • 两者都不可迭代,所以不能使用迭代相关的方法
  • 两者都没有 size 属性

5. 小结

image.png