Closed guyuezhai closed 4 years ago
WeakSet对象允许你将弱引用对象存储在集合中
WeakSet与Set的区别
const arr=[[1,2],[3,4]]
const weakset=new WeakSet(arr)
console.log(weakset)
方法:
var ws=new WeakSet()
var obj={}
var foo={}
ws.add(window) ws.add(obj)
ws.has(window) //true ws.has(fool) //false
ws.delete(window) // true ws.has(window) // false
集合与字典的区别
const mp=new Map()
const o={m:'hello'}
mp.set(o,'content')
mp.get(o) // content
mp.has(o) //true mp.delete(o) //true mp.has(o) //false
任何具有Iterator接口、且每个成员都是一个双元素的数组的数据结构都可以当做Map构造函数的参数
```js
const set=new Set([['foo',1],['bar',2]])
const mp=new Map(set)
mp.get('foo') //1
const mp2=new Map(['baz',3]);
const mp3=new Map(mp2)
mp3.get('baz') // 3
如果读取一个未知的键,则返回undefined
new Map().get('abss') // undefined
只有对同一个对象的引用,Map结构才将其视为同一个键
const map=new Map()
map.set(['a'],'a')
map.get(['a']) //undefined
上面的代码的
set
和get
方法,表面是针对同一个键,但实际上这是两个不同的值,内存地址是不一样的,因此get
方法无法读取改键,返回undefined
由上可知,Map的键实际是内存地址的绑定,只要内存地址不一样,就视为两个不同的键。这就解决了同名属性碰撞的(clash)的问题。
如果Map的键是一个简单类型的值(Boolen,number,string),则只要两个值严格想等,Map将视其为同一个键,比如0
和-0
就是一个键,布尔值true
和字符串true
则是两个不相同的键,另外undefined
和null
也是两个不同的键,虽然NaN
不严格等于自身,但是Map将其视为同一个键
let mp = new Map()
mp.set(-0,123)
mp.get(+0) // 123
mp.set(true,1)
mp.get('true') //undefined
mp.get(true) //1
mp.set(undefined,3)
mp.get(null) //undefined
mp.get(undefined) //3
mp.set(NaN,123)
mp.get(NaN) //123
Map 的属性和方法
const map=new Map([['name','TOM'],['age',20]])
map.size //2
操作方法
遍历方法
const map=new Map([['name','TOM'],['age',20]])
console.log(map.entries()) // MapIterator {"name" => "TOM", "age" => 20}
console.log(map.keys()) // MapIterator {"name", "age"}
console.log(map.values()) // MapIterator {"TOM", 20}
Map 结构的默认遍历器接口(Symbol.iterator属性),就是`entries`方法
```js
map[Symbol.iterator]===map.entries //true
Map 结构转换成数组结构,比较快速的方法是使用扩展运算符(...
)
对于forEach
const loger={
log:function(key,value){
console.log("Key:%s, Value: %s",key,value)
}
}
let map=new Map([['name','TOM'],['age',20]])
map.forEach(function(value,key){
this.log(key,value)
},loger)
//Key:name, Value: TOM
//Key:age, Value: 20
这个例子中,forEach 方法的回调函数的this指向的是loger
与其它数据结构的相互转换
let map=new Map([['name','TOM'],['age',20]])
console.log([...map]) // [Array(2), Array(2)]
let map=new Map([['name','TOM'],['age',20]])
console.log(map) // Map(2) {"name" => "TOM", "age" => 20}
Map 转换成Object
因为Object的键名都是字符串,而Map的键名为对象,所以转换的时候会把非字符串键名转换成字符串键名
function mapToObj(map){
let obj=Object.create(null)
for(let [key,value] of map){
obj[key]=value
}
return obj
}
let map=new Map().set('name','Tom').set('age',20)
mapToObj(map) // {name: "Tom", age: 20}
function objToMap(obj){
let map=new Map()
for(let key of Object.keys(obj)){
map.set(key,obj[key])
}
return map
}
objToMap({name: "Tom", age: 20}) // Map(2) {"name" => "Tom", "age" => 20}
function mapToJson(map){
return JSON.stringify([...map])
}
let map=new Map().set('name','Tom').set('age',20)
mapToJson(map) // "[["name","Tom"],["age",20]]"
function jsonToMap(json){
return objToMap(JSON.parse(json))
}
jsonToMap('{"name": "Tom", "age": 20}') //Map(2) {"name" => "Tom", "age" => 20}
WeakMap 对象是一组键值对的集合,其中的键是弱引用对象,而值可以是任意
WeakMap弱引用的只是键名,而不是键值,键值依然正常引用
WeakMap中,每个键对自己所引用对象的引用都是弱引用,在没有其他引用和该键引用同一个对象的情况下,这个对象将会被垃圾回收(相应的key则会变成无效的),所以,WeakMap的key是不可枚举的
属性:
方法:
let ele=document.getElementById('temp')
let weakmap=new WeakMap();
weakmap.set(ele,{timesClicked:0})
ele.addEventListener('click',function(){
let data=weakmap.get(ele);
data.timesClicked++
},false)
Set 和 Map 主要应用场景在于 数据重组和数据存储 Set 是一种集合的数据结构,Map 是一种字典的数据结构
1. 集合 Set
ES6 新增的一种数据结构,类似于数组,数据成员唯一且无序、不重复
Set 本身是一种构造函数,用来生成Set数据结构
Set 对象允许存储任何类型的唯一值,无论是原始值或者是对象引用
向Set添加值时不会发生类型转换,所以number 3 和 string '3' 是两个不同的值,Set 内部会判断是否两个值相同,使用"Same-value-zero equality"的算法,类似于精确相等运算符(===), 主要的区别是在Set中会把两个为NaN的值当做相等来处理,而在js中会认为NaN与任何值都是不相等的
将 Set 转换成 Array数组
// 利用 Array.from() console.log(Array.from(set)) // [1, 2, 3, 4, 5]
Set 可默认遍历,默认迭代器生成函数是 values()
所以 Set 可以使用map,filter方法
因此使用 Set 很容易实现交集(Intersect)、并集(Union)、差集(Difference)