《十一》ES6+ 中的 Set 和 Map 数据结构

Set(集合):

ES6 新增了一种数据结构 Set,它类似于数组,但是成员的值都是唯一的,没有重复的值。

可以利用 Set 的这个特性为数组去重。

创建 Set 实例:

创建 Set 实例需要通过 Set 构造函数。Set 构造函数可以接受一个可迭代对象作为参数。

const set = new Set([1, 2, 3, 4, 4])
[...set] // [1, 2, 3, 4]

Set 内部判断添加的值是否相同,不会进行类型转换,类似于全等运算符,但是 Set 会认为 NaN 等于自身。

let set = new Set()
set.add(NaN)
set.add(NaN)

set.size // 1

实例属性:

size:返回 Set 实例中的元素个数。

实例方法:

操作方法:
  1. add():添加某个值,返回 Set 实例本身。因此可以链式调用。
  2. delete():删除某个值,返回一个布尔值。
  3. has():判断 Set 实例中是否存在某个值,返回一个布尔值。
  4. clear():清空 Set 实例的所有值,没有返回值。
let s = new Set()
s.add(1).add(2).add(2)

s.size // 2

s.has(2) // true

s.delete(2)
s.has(2) // false
遍历方法:

Set 的遍历顺序就是插入顺序。

  1. keys():返回键名的遍历器;
  2. values():返回键值的遍历器;

    由于 Set 结构的键名和键值是同一个值,所以 keys() 方法和 values() 方法的行为完全一致。

  3. entries():返回键值对的遍历器;
  4. forEach()for...of:遍历 Set 实例。
let set = new Set(['red', 'green', 'blue'])

for (let item of set.keys()) {
  console.log(item);
}
// red
// green
// blue

for (let item of set.values()) {
  console.log(item);
}
// red
// green
// blue

for (let item of set.entries()) {
  console.log(item);
}
// ["red", "red"]
// ["green", "green"]
// ["blue", "blue"]

WeakSet(弱集合):

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

  1. 首先,WeakSet 中只能存放引用类型值,不能存放基本类型值。
  2. 其次,WeakSet 对元素的引用都是弱引用,也就是说,如果其他对象都不再引用某个对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于 WeakSet 之中。

    Set 是强引用。

    // 虽然 obj1 不再指向 {name: 'Lee'},但是 arr 的第一个元素还指向 {name: 'Lee'},因此 {name: 'Lee'} 不会被销毁
    let obj1 = {name: 'Lee'}
    let arr = [obj1]
    obj1 = null
    console.log(obj1) // null
    console.log(arr[0]) // {name: 'Lee'}
    
    // obj2 不再指向 {name: 'Lee'},同时由于 WeakSet 对对象的引用时弱引用,因此 {name: 'Lee'} 随时可能垃圾回收器被销毁
    let obj2 = {name: 'Lee'}
    let s = new WeakSet()
    s.add(obj2)
    obj = null
    console.log(obj) // null
    console.log(s)
    

实例属性:

WeakSet 没有 size 属性。

实例方法:

WeakSet 与 Set 在实例方法上的区别主要是有两个:一是无法清空,即不支持 clear 方法;二是没有遍历操作。

WeakSet 不能进行遍历,是因为元素都是弱引用,随时可能消失,遍历机制无法保证元素的存在,很可能刚刚遍历结束,成员就取不到了。

Map(映射):

JavaScript 的对象,本质上是键值对的集合,但是传统上只能用字符串当做键,这给它的使用带来了很大的限制。

// 原意是将一个 DOM 节点作为对象 data 的键,但是由于对象只接受字符串作为键名,所以 element 被自动转为字符串 [object HTMLDivElement]
const data = {}
const element = document.getElementById('myDiv')
data[element] = 'metadata'
data['[object HTMLDivElement]'] // "metadata"

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

创建 Map 实例:

创建 Map 实例需要通过 Map 构造函数。Map 构造函数可以接受一个每个成员都是一个双元素数组的可迭代对象作为参数(也就是说,参数首先需要是一个可迭代对象,其次可迭代对象的每个成员都需要是一个双元素的数组)。

const map = new Map([
  ['name', '张三'],
  ['title', 'Author']
]);

map.size // 2
map.has('name') // true
map.get('name') // "张三"

Map 构造函数接受数组作为参数,实际上执行的是下面的算法。

const items = [
 ['name', '张三'],
 ['title', 'Author']
]
const map = new Map()
items.forEach(
 ([key, value]) => map.set(key, value)
);

实例属性:

size: 返回 Map 实例的元素个数。

const map = new Map()
map.set('name', 'Lee')

map.size // 1

实例方法:

操作方法:
  1. set(key,value):设置键名 key 对应的键值为 value。如果 key 已经有值,则键值会被更新,否则就新生成该键。返回 Map 实例,因此可以链式调用。
    const m = new Map()
    m.set('name', 'Lee').set(undefined, 'man')    // 键是 undefined
    
  2. get(key):读取 key 对应的 value。如果找不到 key,返回 undefined。
  3. has(key):判断是否包含某个 key。返回一个布尔值。
  4. delete(key):根据 key 删除某个 value。返回一个布尔值。
  5. clear():删除所有元素。没有返回值。
遍历方法:
  1. keys():返回键名的遍历器。
  2. values():返回键值的遍历器。
  3. entries():返回键值对的遍历器。
  4. forEach()for...of:遍历 Map。

WeakMap(弱映射):

WeakMap 结构与 Map 结构类似,也是用于生成键值对的集合。区别有两点:

  1. 首先,WeakMap 的键名 key 只能是对象(null 除外),不接受其他类型。
  2. 其次,WeakMap 的键名 key 所指向的对象,对其的引用是弱引用。
const map = new WeakMap()
map.set(1, 2) // TypeError: 1 is not an object!
map.set(null, 2) // TypeError: Invalid value used as weak map key

实例属性:

WeakMap 没有 size 属性。

实例方法:

WeakMap 与 Map 在实例方法上的区别主要是有两个:一是无法清空,即不支持 clear 方法;二是没有遍历操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值