ES6提供了新的数据结构Set,相似数组,元素值都是惟一的,不能重复。Set自己就是一个构造函数。数组
Set接受数组或者类数组做为参数用来初始化:bash
var arr1 = new Set([1, 2, 5, 1, 2]);
var arr2 = new Set('12512');
console.log(arr1);
console.log(arr2);
复制代码
var arr = new Set([NaN, NaN]);
console.log(arr);//NaN
console.log(NaN === NaN);//false
复制代码
Set的属性和方法:数据结构
Add(value),添加某个值,返回Set结构自己:函数
var arr = new Set();
arr.add(1);
arr.add(2);
console.log(...arr);//1 2
复制代码
Delete(value),删除某个值,返回布尔值,表示成功失败:ui
console.log(arr.delete(1));//truespa
has(value),返回一个布尔值,表示该值是否为Set的成员。code
console.log(arr.has(2));//trueorm
Clear(),清除全部元素,无返回值:cdn
arr.clear();对象
console.log(arr);//{}
Size,返回元素总数:
console.log(arr.size);//2
Array.form能够把Set数据结构转成数组,能够用来去重:
var arr = [1, 2, 1, 3, 4, 3, 2, 1, 5, 2];
var setArr = new Set(arr);
console.log(Array.from(setArr));//[1, 2, 3, 4, 5]
复制代码
遍历keys、values、entries:
Set数据结构没有键名,也能够说键名键值是同一个,因此这三个遍历出来的都同样,区分的话就是keys是键名,values是键值,entries是键值对:
var arr = new Set(['a', 'b', 'c']);
for(var i of arr.keys()){
console.log(i);//a b c
}
for(var i of arr.values()){
console.log(i);//a b c
}
for(var i of arr.entries()){
console.log(i);//['a', 'a'] ["b", "b"] ["c", "c"]
}
复制代码
Set结构默承认遍历,默认遍历的就是values,能够用for of直接遍历:
for(var i of arr){
console.log(i);//a b c
}
复制代码
Set结构也能够用forEach遍历,由于Set结构能够用扩展运算符,能够变通的数组去重和使用数组的遍历方法:
var arr = [1, 2, 1, 3, 4, 3, 2, 1, 5, 2];
console.log([...new Set(arr)]);//[1, 2, 3, 4, 5]
复制代码
ES6提供了跟Set结构相似的WeakSet,也是不重复的集合,可是WeakSet只能是对象,其余类型的值都会报错:
var ws = new WeakSet();
ws.add(1)//TypeError
ws.add('a')//TypeError
ws.add({a: 10})
复制代码
垃圾回收机制不会回收被全局引用的变量,而WeakSet 中的对象都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用。
若是其余对象都再也不引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于 WeakSet 之中。
WeakSet 里面的引用,都不计入垃圾回收机制,所以,WeakSet 适合临时存放一组对象,以及存放跟对象绑定的信息。只要这些对象在外部消失,它在 WeakSet 里面的引用就会自动消失。
因为上面这个特色,WeakSet 的成员是不适合引用的,由于它会随时消失。另外,因为 WeakSet 内部有多少个成员,取决于垃圾回收机制有没有运行,运行先后极可能成员个数是不同的,而垃圾回收机制什么时候运行是不可预测的,所以 ES6 规定 WeakSet 不可遍历。
总结一下就是,WeakSet的实例对象就算是全局的,也有能够被直接回收。
WeskSet有add、delete、has方法没跟Set同样,可是只能是对象或者相似对象的数组,好比:
var ws = new WeakSet();
ws.add([[1, 1], [2, 2]])
WeakSet没有size属性,不能遍历。所以WeakSet的一个做用就是用来存储DOM节点。其余还真不知道什么用。
ES6提供了Map数据结构本质上仍是键值对的集合,可是传统对象只能是字符串作键名,好比:
var el = document.getElementById('te');
var obj = {};
obj[el] = 'te';
console.log(obj);//{[object HTMLDivElement]: "te"}
复制代码
Map数据结构最主要的就是解决这个问题,键值还能够是对象:
var el = document.getElementById('te');
var obj = new Map();
obj.set(el, 'te');
console.log(obj);//{{div#te => "te"}
复制代码
Map有set、get、delete、clear和has方法和size属性:
console.log(obj.get(el));//'te'
console.log(obj.has(el));//true
console.log(obj.size);//1
obj.delete(el);
obj.clear();
console.log(obj.has(el));//false
复制代码
Map接收的数组参数的时候,必定是这样的:
var obj = new Map([['a', 'a'], ['b', 'b']]);
其余的操做就跟普通对象操做原理同样,只有一个须要注意,Map的键跟内存地址有关:
var map = new Map();
map.set(['a'], 123);
console.log(map.get(['a']));//undefined
复制代码
数组的内存地址是不一样的
map.set(-0, 123);
console.log(map.get(+0)); // 123
map.set(true, 1);
map.set('true', 2);
console.log(map.get(true)); // 1
console.log(map.get('true')); // 2
map.set(undefined, 3);
map.set(null, 4);
console.log(map.get(undefined)); // 3
map.set(NaN, 123);
console.log(map.get(NaN)); // 123
复制代码
Map和Set同样,也有keys、values、entries和forEach遍历方法,且顺序就是插入顺序,使用for of方法,一样的,使用扩展运算符也能很快的转为数组,转成数组以后也就间接的能使用数组的map、filter等数组方法。这边就不上代码了,跟Set同样。
Map数据结构,能够直接或者间接的准成数组或者JSON或者对象,相应的,数组或者JSON或者对象也能转成Map数据结构。
ES6提供了跟Map相似的WeakMap数据结构,二者都差很少,区别有两点,第一就是WeakMap的键必定要对象,不然报错,另一点跟WeakSet同样,不计入垃圾回收机制。
它的键名所引用的对象都是弱引用,即垃圾回收机制不将该引用考虑在内。所以,只要所引用的对象的其余引用都被清除,垃圾回收机制就会释放该对象所占用的内存。也就是说,一旦再也不须要,WeakMap 里面的键名对象和所对应的键值对会自动消失,不用手动删除引用。
要注意的是,是键名是弱引用,键值依然可使用:
var map = new WeakMap();
var key = {};
var val = 'map';
map.set(key, val);
val = null;
console.log(map.get(key));//map
复制代码
也就是说val即便是消除了,WeakMap内部依然能使用。
由于WeakMap和Map的区别,键名是否存在不可预测,跟垃圾回收机制是否运行有关,因此WeakMap其余方法都没有只有get、set、has、delete方法。
WeakMap典型场合也是DOM节点做为键名,一旦DOM节点删除了,WeakMap里面的也会随之消失,不会形成内存泄漏风险:
var map = new WeakMap();
var key = document.getElementById('te');
var val = 1;
map.set(key, val);
key.addEventListener('click', function() {
let val = myWeakmap.get(myElement);
val++;
}, false);
复制代码
一旦DOM节点消失,那么该val也会消失。
Coding 我的笔记