Set和Map是ES6里新增的两种数据结构。本身都是一种构造函数,用来生成对应的数据结构。
Set数据结构只有键,没有与键关联的值(或者认为键名键值是同一个),Map数据结构存储键值对,其中键的数据类型不局限于字符串而可以是任何数据类型;
Set
Set()
本身是构造函数,通过new
命令可以创建一个新的Set数据结构,接收一个数组或任何其他具有Iterator接口的数据结构可以初始化Set结构,通过add()
方法可以向Set结构添加新值。
Set结构不会保存重复的值,如果已有重复的值会添加无效;
对于重复值的判断采用全等判断,但与全等判断有一点不同,这里NaN
会被认为与自身相等。如果是对象,则不是相同的引用也会被视为不相等;
实例属性和方法
Set.prototype.constructor
,构造函数,默认为Set
函数;
Set.prototype.size
,Set结构的成员总数;
add(value)
添加值,返回Set结构本身;delete(value)
删除值,返回布尔值,表示删除是否成功;has(value)
判断是否有该值,返回布尔值;clear()
清除所有成员,没有返回值;
将Set结构转为数组:
let a = new Set([1,2,"abc"]);
let b = [...a];
let c = Array.from(a);
console.log(b); // [1, 2, "abc"]
console.log(c); // [1, 2, "abc"]
Set结构的遍历方法(遍历顺序就是插入顺序)
keys()
键名values()
键值entries()
键值对forEach(func)
使用回调函数遍历每个成员;可以有第二个参数用于绑定处理函数内部的this对象;
在Set数据结构里键名和键值是同一个,所以keys()
和values
的行为是一样的,entries()
返回的遍历器同时包括键名和键值(相等),输出数组;
weakSet
与Set相似,也是不重复的值的集合;但成员必须是对象;该数据结构中对对象是弱引用,不在垃圾回收考虑的引用范围内;
- WeakSet.prototype.add(value) 添加成员
- WeakSet.prototype.delete(value) 删除指定成员
- WeakSet.prototype.has(value) 返回布尔值,表示指定值是否已存在于实例中
Map
Map数据结构是键值对的集合,类似于对象,但键值可以是包括字符串类型的任何数值类型。
使用let a = new Map()
可以查创建一个新Map结构;
添加成员(set()
)和读取(get()
)成员:
let a = new Map();
let n = [1,2];
a.set(n,"first");
console.log(a.get(n)); // "first"
查看成员数量,删除成员,判断是否有某个成员
console.log(a.size); // 1
console.log(a.has(n)); // true
a.delete(n);
console.log(a.has(n)); // false
clear()
方法可以清除所有成员,无返回值;
Map中判断键名是否重复与Set类似,对于对象键名,如果引用的是同一个对象则是相同的,否则就算字面量相同也是不同的键名;
遍历方法
keys()
返回键名的遍历器values()
返回键值的遍历器entries()
返回键值对的遍历器forEach()
遍历所有成员,
借用数组的map()
和filter()
方法:
let a = new Map().set(1,"one").set(2,"two").set(3,"three");
let b = [...a].filter(([k, v]) => k < 3);
console.log(b); // [[1, "one"], [2, "two"]]
console.log(a); // {1 => "one", 2 => "two", 3 => "three"}
Map与对象互相转换:
// 如果有非字符串的键名,会被先转换为字符串,在作为对象的键名
function mapToObj(map0) {
let obj0 = {};
for (let [k, v] of map0.entries()) {
obj0[k] = v;
}
return obj0;
}
console.log(mapToObj(a));
//{1: "one", 2: "two", 3: "three"}
function objToMap(obj0) {
let map0 = new Map();
for (let key of Object.keys(obj0)) {
map0.set(key, obj0[key]);
}
return map0;
}
console.log(objToMap({1:"a", 2:"aa", 3:"aaa"}));
// Map(3) {"1" => "a", "2" => "aa", "3" => "aaa"}
对于JSON,则需要对象作为中转;而如果键名有对象,则用数组作为中转。
weakMap
与Map的区别:
- 只接受对象作为键名,不接受其他类型值;
- 对象键名不计入垃圾回收机制;
weakMap的方法只有set()
, get()
, has()
, clear()
,没有遍历操作和size
属性。