《ES6标准入门》阅读笔记——-set和map

写在前面

本系列为在我读完阮一峰老师的《ES6标准入门》第二版之后,所做的阅读笔记的整理。

许多初学ES6, 同时和我一样初次阅读阮老师的这本书的时候, 读第一遍会越发的困惑, 因为阮老师上面说的很多的定义,方法,之前都是没有见过的, 读到后面才发现, 哦~原来是这样.

有一句话叫做”大神的世界我们不懂”, 所以我在初读第一遍《ES6标准入门》这本书的时候,也是踩了不少坑,读书的时候查阅了不少的资料.

所以,在这一系列的笔记教程中,我会从一个初学者的角度,向您讲述ES6的相关知识,在后面介绍的知识我会尽量不提前用,即使提前使用,也会同时做好标注,避免了阅读时各种查阅资料的烦恼.

系列博客将采用一个一个的样例,来说明书中的精华部分(当然,这只是我认为的),同时引导新手,快速入门ES6,并逐步将其投入到生产实践中。

同时,在阅读前也提醒您, 为了系统连贯性的学习ES6的基础知识,建议您从我的博客第一章开始阅读,当然,如果您对对应的知识已经有所了解,那么可以跳转到任意章节阅读,每一篇博客名中均有介绍该博客中涉及到的ES6的内容.

阮一峰老师的这本书是开源的,在其官方博客就可以下载到,但是我强烈建议大家去购买一本书, 一是方便自己查阅ES6中新增的众多API, 二也是表达一下对大神的敬仰.

Set

ES6提供了一种新的数据结构Set,类似于数组,但成员值是唯一的,没有重复值. set本身是一个构造函数,用来生成set数据结构

因此, 利用set这个结构的特性, 就可以很容易地进行数组去重了

1
2
3
let s = new Set();
let a = [1, 2, 3, 4, 5, 5, 6, 2, 12, 53, 34, 5, 1, 2, 5, 3, 1, 1].map(x => s.add(x))
console.log(...s) // 1 2 3 4 5 6 12 53 34

向set加入值的时候不会发生类型转换,所以 5 和 ‘5’ 是两个不同的值

在set内部判断两数是否相等使用的是精确相等运算符, 也就是说,当我们比较对象是否相等的时候,两个不同引用空间的对象是永远不相等的

有一个例外是,当我们使用NaN的时候,会发现两个NaN其实是相等的,而在ES5的时候NaN会被认为是一个Object从而判定两者不相等

1
2
3
4
5
let set = new Set([1, 2, 3, NaN, NaN])
console.log(set.size) // 4
set.add({})
set.add({})
console.log(set.size) // 6

由上面的打印结果很明显的能看到, 两个NaN是相等的, 但是两个对象是不等的

set结构的实例是默认可遍历的

1
2
3
4
let set = new Set(['red', 'green', 'blue'])
for (let x of set) {
console.log(x) // red green blue
}

由于扩展运算符内部使用for…of循环,所以也可以用于set结构

set的使用技巧

利用set可以很容易地实现并集 交集 差集的操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
let a = new Set([1, 2, 3])
let b = new Set([2, 3, 4])

// 求并集
let union = new Set([...a, ...b])
console.log(union) // Set(4) {1, 2, 3, 4}

// 求交集
let intersect = new Set([...a].filter(x => b.has(x)))
console.log(intersect) // Set(2) {2, 3}

// 求差集
let difference = new Set([...a].filter(x => !b.has(x)))
console.log(difference) // Set(1) {1}

WeakSet

WeakSet的结构和Set类似,也是不重复的值的集合.但是,它与Set有两个区别

    1. weakset成员只能是对象,不能是其他类型的值
    1. weakset对象都是弱引用,即垃圾回收机制不考虑

weakset对该对象的引用,如果其他对象都不再引用该对象,那么该对象就会被GC回收.

这一特点意味着无法引用weakset的成员,因此weakset是不可遍历的

Map

javascript的对象本质上是键值对的集合,但是只能用字符串作为键名

1
2
3
4
5
6
let data = {}
let element = document.getElementById('myDiv')

data[element] = metadata // 报错

console.log(data['[Object HTMLElement]'])

ES6提供了Map数据结构,它类似于对象,也是键值对的集合,但是键的范围不限于字符串,各种类型的值都可以当做键名

因此,map是比object更加合适的键值对结构

1
2
3
4
5
6
7
8
9
10
let m = new Map()
let o = {
p: 'Hello world'
}
m.set(o, 'content')
console.log(m.get(o)) // content

console.log(m.has(o)) // true
console.log(m.delete(o)) // true
console.log(m.has(o)) // false

另外有一点需要注意的是,map的键是和内存地址绑定的,只要内存地址不一样,那么就会被视为两个键, 这样就解决了同名属性的碰撞问题

1
2
3
4
5
6
7
8
9
10
let map = new Map()

let k1 = ['a']
let k2 = ['a']

map.set(k1, 111)
map.set(k2, 222)

console.log(map.get(k1)) // 111
console.log(map.get(k2)) // 222

那么同样的,当我们使用简单数据类型时,只要两值完全相等,map就将其视为一个键

包括+0 和 -0 , 以及NaN

1
2
3
4
5
6
7
let map = new Map()

map.set(NaN, 123)
console.log(map.get(NaN)) // 123

map.set(-0, 321)
console.log(map.get(+0)) // 321

map结构转为数组结构比较方便的方法就是使用三点运算符,或者说是扩展运算符,或者说是rest参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
let map = new Map([
[1, 'one'],
[2, 'two'],
[3, 'three']
])

console.log([...map.keys()])
// 1 2 3
console.log([...map.values()])
// "one" "two" "three"
console.log([...map.entries()])
// [1, "one"] [2, "two"] [3, "three"]
console.log([...map])
// [1, "one"] [2, "two"] [3, "three"]

WeakMap

Weakmap的结构和map结构基本类似,但是weakmap只接受对象作为键名,不接受其他类型的值作为键名

weakmap的应用典型场景就是在DOM节点作为键名的时候

1
2
3
4
5
6
7
8
9
10
11
12
let myElement = document.getElementById('logo')
let myWeakmap = new WeakMap()

myWeakmap.set(myElement, {
timesClicked: 0
})

myElement.addEventListener('click', () => {
let logoData = myWeakmap.get(myElement)
logoData.timesClicked++
myWeakmap.set(myElement, logoData)
}, false)

(完)

文章目录
  1. 1. 写在前面
  2. 2. Set
  3. 3. set的使用技巧
  4. 4. WeakSet
  5. 5. Map
  6. 6. WeakMap
|