ES6之Set和Map数据结构

ES6提供了新的数据结构Set,类似数组,元素值都是唯一的,不能重复。Set本身就是一个构造函数。

Set接受数组或者类数组作为参数用来初始化:

var arr1 = new Set([1, 2, 5, 1, 2]);

var arr2 = new Set('12512');

console.log(arr1);

console.log(arr2);


会把重复的都去除,但是不会发生类型转换,Set内部判断两个值类似===运算符,主要的区别就是NaN等于自身,三等的NaN会不等于自身。

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),删除某个值,返回布尔值,表示成功失败:

console.log(arr.delete(1));//true

has(value),返回一个布尔值,表示该值是否为Set的成员。

console.log(arr.has(2));//true

Clear(),清除所有元素,无返回值:

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 个人笔记

猜你喜欢

转载自blog.csdn.net/wade3po/article/details/89703291
今日推荐