set,map,WeakSet,Weakmap 在js的使用频率越来越高,特备是一些新框架的源码中,本篇博文将其基本用法和区别做一总结,加强记忆。
如何理解唯一性:对于原始数据类型(boolean,number,string,null,undefined)如果存储相同值则只会保存一个,对于引用类型做“==”判断即引用地址完全相同则只会存一个。
let set = new Set();
//a,b属于object 值完全相同
let a = {
name:"cc",
age:28
};
let b = {
name:"cc",
age:28
};
//c,d属于number类型 值完全相同
let c = 0,d = 0;
//e,f 属于Date类型,值相同
let e=f = new Date();
set.add(a);
set.add(b);
set.add(c);
set.add(d);
set.add(e);
set.add(f);
a= "abc";
b = {
name:"cc",
age:30
}
set.add(a);
set.add(b);
console.log(set);
鉴于set存储值的不重复特性,经常被用来求数组去重,交集,并集,差集等操作。
let arry = [1, 2, 3, 4, 4,1,2,3,2];
var mySet = new Set(arry);
let newArry = [...mySet]; // [1, 2, 3, 4]
//set求并集
let arryA= [2,3,4,5,6],arryB = [3,4,5,6,7,8];
let setAB = new Set([...arryA,...arryB]);
let newArryAB = [...setAB];
console.log(newArryAB); //[2,3,4,5,6,7,8]
//求交集
let arryC= [2,3,4,5,6],arryD = [3,4,5,6,7,8];
let setC = new Set(arryC);
let setD = new Set(arryD);
let newArryC_D = arryA.filter(x=>setD.has(x));
console.log(newArryC_D); //[3,4,5,6]
//求差集
let newArryD_C = arryA.filter(x=>!setD.has(x));
let newArryD_D = arryB.filter(x=>!setC.has(x));
let newArryCD = [...newArryD_C,...newArryD_D];
console.log(newArryCD); //[2,7,8]
Map 对象保存键值对。任何值(对象或者原始值) 都可以作为一个键或一个值。
Map常用属性及增删改查方法:
与Object的区别:
let map = new Map();
let s = {
name:'cc',
job:'programmer'
}
let m ={
dd:'cdcdcd',
do:function(str){
console.log(str)
}
}
map.set(s,m);
map.set(m,s);
map.set(0,s);
map.set(0,m);
console.log(map)
for … of
forEach
for(let [key,value] of map){
console.log("key:"+JSON.stringify(key)+"-------value:"+JSON.stringify(value))
}
map.forEach((value,key)=>{
console.log("key:"+JSON.stringify(key)+"-------value:"+JSON.stringify(value))
})
map与数组之间的转换
let arryK = [[1,2],[3,4],[5,6]];
let mapK = new Map(arryK);
let mapP = Array.from(mapK);
console.log(mapK);
console.log(mapP);
let mapV= new Map(map);
和Set结构类似,也是不重复的值的集合,但WeakSet的成员只能是对象。
WeakSet的API:add() //增 ;delete() //删; has() //是否存在
注意:ws没有size属性,不可遍历。因为WeakSet的成员都是弱引用,随时可能消失,成员是不稳定的。
WeakSet的用处:
(1)使用ws储存DOM节点,就不用担心节点从文档移除时,会引发内存泄漏(即在被移除的节点上绑定的click等事件)。
(2)下面代码保证了Foo的实例方法,只能在Foo的实例上调用。这里使用 WeakSet 的好处是,foos对实例的引用,不会被计入内存回收机制,所以删除实例的时候,不用考虑foos,也不会出现内存泄漏。
WeakMap与Map的区别:
WeakMap 对象是一组键值对的集合,其中的键是弱引用对象,而值可以是任意。
注意,WeakMap 弱引用的只是键名,而不是键值。键值依然是正常引用。
WeakMap 中,每个键对自己所引用对象的引用都是弱引用,在没有其他引用和该键引用同一对象,这个对象将会被垃圾回收(相应的key则变成无效的),所以,WeakMap 的 key 是不可枚举的。
用WeakMap来实现私有属性
//weakmap
let Person = (function() {
let privateData = new WeakMap();
function Person(name,age) {
privateData.set(this, {name:name,age:age});
}
Person.prototype.getName = function() {
return privateData.get(this).name;
};
Person.prototype.getAge = function() {
return privateData.get(this).age;
};
Person.prototype.setName = function(name) {
let obj = privateData.get(this)
obj.name = name;
};
Person.prototype.setAge = function(age) {
let obj = privateData.get(this)
obj.age = age;
};
return Person;
}());
let ssf = new Person("zhang",19);
console.log(ssf.getName());
console.log(ssf.getAge());
ssf.setName("liu");
ssf.setAge(90)
console.log(ssf.getName());
console.log(ssf.getAge());