Set
类似于数组,但是没有重复值
基础用法
通过new Set()构造一个set实例,通过add方法向set添加元素
var set = new Set([1,2,3,4,4,4]);
set.add(5);
set.add(6);
set.add('6');
console.dir(set);
上面代码运行结果如下:
注意 数字6 和 字符串6
去除数组重复值
利用set可以用来去除数组中重复值
var a = [1,2,3,4,5,1,2];
var b = [...new Set(a)];
操作方法:
添加元素:add(value)
删除元素:delete(value)
是否存在元素:has(value)
清空:clear()
var set = new Set();
set.add(1);
set.add(1);
set.add(2);
console.log(set.has(1));// true
console.log(set.has(3));// false
console.log(set.size);// 2
set.delete(1);
console.log(set.has(1));// false
console.log(set.size);// 1
set.clear();
console.log(set.size);// 0
遍历方法:
返回键名的遍历器:keys()
返回键值的遍历器:values()
返回键值对的遍历器:entries()
使用回调函数遍历:forEach()
var set = new Set();
set.add(1);
set.add(2);
set.add(3);
set.add(3);
for (let i of set) {
console.log(i);
}
// 1
// 2
// 3
for (let i of set.keys()) {
console.log(i);
}
// 1
// 2
// 3
for (let i of set.values()) {
console.log(i);
}
// 1
// 2
// 3
for (let i of set.entries()) {
console.log(i);
}
// [1, 1]
// [2, 2]
// [3, 3]
console.log(set.keys === set.values); // true
set.forEach((value, key) => {
console.log(`${value} : ${key}`);
})
// 1 : 1
// 2 : 2
// 3 : 3
因为Set没有键名,只有键值
所以set.keys()返回值和set.values()返回值一模一样
也因此set.entries()的键值也一样
间接使用map和filter
通过将Set转换成Array进行map或filter处理后,再转换回Set
var set = new Set([1,2,3]);
set = new Set([...set].map(x => x * 2));
console.dir(set);
set = new Set([...set].filter(x => x > 2));
console.dir(set);
利用Set获取并集、交集、差集
var a = new Set([1, 2, 3]);
var b = new Set([2, 3, 4]);
// 并集
var union = new Set([...a, ...b]);
// 交集
var intersect = new Set([...a].filter(x => b.has(x)))
// 差集(a相对于b)
var difference = new Set([...a].filter(x => !b.has(x)))
console.dir(union)
console.dir(intersect)
console.dir(difference)
WeakSet
WeakSet与Set结构类似,都不能存重复值
不同点在于:
WeakSet的成员只能是对象类型
成员对象都是弱引用的,当没有引用时,垃圾回收机制会自动回收该对象占用的内存
应用:用于保存Dom节点,不用担心这些节点从文档移除时,会引发内存泄漏
var set= new WeakSet();
var dom = document.getElementById('myDiv');
set.add(dom);
set.delete(dom);
set.has(dom);
Map
JavaScript的Object类型只能接受字符串作为键,Map类似于Object,也是键值对的集合,但是键可以是各种值(包括Object)
var m = new Map([['name', 'map name']]);
var o = {name: 'object name'}
m.set(o, o.name);
console.dir(m)
Map构造函数接受一个数组作为参数,此数组的成员是一个个表示键值对的数组
操作方法:与Set一样
var m = new Map();
m.set(['a'], 'arr 1');
console.log(m.get(['a'])); // undefined
上面代码中的两个['a']是不同的实例,内存地址是不一样的,所以无法获取到值
Map的键是跟内存绑定的,只要内存地址不同,就是不同的键
let m = new Map();
m.set(-0, 123);
m.get(+0) // 123
m.set(true, 1);
m.set('true', 2);
m.get(true) // 1
m.get('true') // 2
m.set(undefined, 3);
m.set(null, 4);
m.get(undefined) // 3
m.get(null) // 4
m.set(NaN, 123);
m.get(NaN) // 123
如果 Map 的键是一个简单类型的值(数字、字符串、布尔值),则只要两个值严格相等,Map 将其视为一个键,比如0
和-0
就是一个键,布尔值true
和字符串true
则是两个不同的键。另外,undefined
和null
也是两个不同的键。虽然NaN
不严格相等于自身,但 Map 将其视为同一个键。
遍历方法:与Set一样
const map = new Map([
[1, 'one'],
[2, 'two'],
[3, 'three'],
[['a'], 'four', 'four2'],
[{}, 'five'],
]);
console.dir([...map.keys()])
console.dir([...map.values()])
console.dir([...map.entries()])
console.dir([...map])
WeakMap
只接受对象作为键名(null
除外)
WeakMap
的键名所指向的对象,不计入垃圾回收机制