ES6 Set 和 Map 数据结构的使用
ES6 提供了 Set 和 Map 这两种数据结构,相比于之前的对象和数组,我们有了更多的选择。这篇文章主要讲解它们的使用方式以及一些好的实践。
Set
基本特性
- 它类似于数组,但是成员的值都是唯一的,没有重复的值。
- Set 构造函数接收可迭代对象作为参数,用来初始化。
- 向 Set 加入值时,使用的算法叫做
Same-value-zero equality
,它类似于精确相等运算符(===),不会发生类型转换。跟===
唯一不一样的地方是,向它加入两个NAN
认为是相等的。另外,两个对象总是不相等。
const set = new Set([5, '5', {}, {}, NaN, NaN])
console.log(set) // Set { 5, '5', {}, {}, NaN }
// 添加两个对象,是不同的元素
let set = new Set();
set.add({});
set.size // 1
set.add({});
set.size // 2
属性和方法
const mySet = new Set()
// add 添加元素
mySet.add(1)
mySet.add('jack')
// delete 删除元素
mySet.delete(1)
// 清空Set
mySet.clear()
方法都比较简单,主要注意一下entries
,与数组不一样的是,返回的是一个[value, value]
的可迭代对象。
//entries 返回一个迭代器对象,[value, value]
const setIter = set.entries()
for (let [value] of setIter) {
console.log(value)
}
扩展运算符(...)内部使用for...of循环
,所以也可以用于 Set 结构。
let set = new Set(['red', 'green', 'blue']);
let arr = [...set];
// ['red', 'green', 'blue']
Array.from
方法可以将 Set 结构转为数组。
const items = new Set([1, 2, 3, 4, 5]);
const array = Array.from(items);
最佳实践
// 去除数组的重复成员
[...new Set(array)]
// 去除重复字符
[...new Set('ababbc')].join('')
Map
基本特性
Map
相比于Set
来说,使用地更加频繁一些。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了“字符串 — 值”的对应,Map 结构提供了“值 — 值”的对应,是一种更完善的 Hash 结构实现。如果你需要“键值对”的数据结构,Map 比 Object 更合适。
map 键的比较是基于sameValueZero
算法:NaN
与NaN
是相等的,其他的都是类似===
属性和方法
map 的构造函数需要注意一下,它接收的是一个键值对类型的可迭代对象。
例如: [[ 1, 'one' ],[ 2, 'two' ]])
。 每个键值对都会添加到新的 Map
。
数组转 Map
const arr = [
[true, 7],
['name', 'jack'],
]
const map1 = new Map(arr)
console.log(map1) // Map { true => 7, 'name' => 'jack' }
对象转map
const person = {
name: 'jack',
age: 18,
sex: 'male',
}
const map2 = new Map(Object.entries(person))
console.log(map2) // Map { 'name' => 'jack', 'age' => 18, 'sex' => 'male' }
Json转map
function jsonToStrMap(jsonStr) {
return objToStrMap(JSON.parse(jsonStr));
}
jsonToStrMap('{"yes": true, "no": false}')
map的遍历
const map = new Map([
['F', 'no'],
['T', 'yes'],
]);
for (let key of map.keys()) {
console.log(key);
}
// "F"
// "T"
for (let value of map.values()) {
console.log(value);
}
// "no"
// "yes"
for (let item of map.entries()) {
console.log(item[0], item[1]);
}
// "F" "no"
// "T" "yes"
// 或者
for (let [key, value] of map.entries()) {
console.log(key, value);
}
// "F" "no"
// "T" "yes"
// 等同于使用map.entries()
for (let [key, value] of map) {
console.log(key, value);
}
// "F" "no"
// "T" "yes"
最佳实践
- 使用
Map
替代switch
switch
function animalSpeak(animalType) {
switch (animalType) {
case 'dog':
console.log('Wang!');
break;
case 'cat':
console.log('Miaow!');
break;
case 'bird':
console.log('Jiu!');
break
}
}
animalSpeak('dog');
Map
const animalSpeak = {
dog: ()=>console.log('Wang!'),
cat: ()=>console.log('Miaow!'),
bird: ()=>console.log('Jiu!'),
};
animalSpeak['dog']();
2. 作为hash
表
const number = [1, 2, 3]
const map = new Map(number.map((item, index) => [item, index]))
console.log(map)
// Map { 1 => 0, 2 => 1, 3 => 2 }
WeakSet 与 WeakMap
WeakSet
与Set
的两个区别:
- 成员只能是对象,而不能是其他类型的值;
- WeakSet 里面的引用,都不计入垃圾回收机制
WeakMap
与Map
的两个区别:
- WeakMap只接受对象作为键名(null除外),不接受其他类型的值作为
- WeakMap的键名所指向的对象,不计入垃圾回收机制。