1 为什么要使Map
es5之前对象的key只能使用字符串,就算不加双引号,在底层实现的时候也是字符串。es6之后,可以使用symbol类型作为key值。总结就是:对象的key只能使用字符串或者symbol。但是对象的value可以是任何类型。
// 1.JavaScript中对象中是不能使用对象来作为key的
const obj1 = { name: "why" }
const obj2 = { name: "kobe" }
const info = {
[obj1]: "aaa",
[obj2]: "bbb"
}
console.log(info)
//[object Object]: "bbb"
//当把obj1作为key的时候,会把obj1转换为一个字符串格式
//obj1转成字符串之后就是[object object]
console.log(obj1.toString());//[object Object]
//obj2的key会把前面的覆盖掉
2 Map的基本使用
106.PNGMap这种数据结构就是允许我们对象类型或者其他类型来作为key的。
ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。如果你需要“键值对”的数据结构,Map 比 Object 更合适。
// 2.Map就是允许我们对象类型来作为key的
const obj1 = { name: "why" }
const obj2 = { name: "kobe" }
const map = new Map()
map.set(obj1, "aaa")
map.set(obj2, "bbb")
console.log(map);
//Map(2) {{…} => 'aaa', {…} => 'bbb'}
map.set(1, "ccc")
//也可以使用基本数据类型作为key
// 构造方法的使用
//作为构造函数,Map 也可以接受一个数组作为参数。该数组的成员是一个个表示键值对的数组。
//new Map([[key, value], [key,value], [key,value]])
const map2 = new Map([[obj1, "aaa"], [obj2, "bbb"], [2, "ddd"]])
console.log(map2)
//Map(3) {{…} => 'aaa', {…} => 'bbb', 2 => 'ddd'}
3 Map的常用方法
107.PNG//3.常见的属性和方法
//size:返回Map中元素的个数;
const obj1 = { name: "why" }
const obj2 = { name: "kobe" }
const map2 = new Map([[obj1, "aaa"], [obj2, "bbb"], [2, "ddd"]])
console.log(map2.size);//3
//set(key, value):在Map中添加key、value,并且返回整个Map对象;
map2.set("why", "eee")
console.log(map2)//Map(4) {{…} => 'aaa', {…} => 'bbb', 2 => 'ddd', 'why' => 'eee'}
console.log(map2.set("why", "eee"));
//Map(4) {{…} => 'aaa', {…} => 'bbb', 2 => 'ddd', 'why' => 'eee'}
//get(key):根据key获取Map中的value;
console.log(map2.get("why"))//eee
console.log(map2.get(obj1))//aaa
//has(key):判断是否包括某一个key,返回Boolean类型;
console.log(map2.has("why"))//true
console.log(map2.has(obj1))//true
//delete(key):根据key删除一个键值对,返回Boolean类型;
map2.delete("why")
console.log(map2)
//Map(3) {{…} => 'aaa', {…} => 'bbb', 2 => 'ddd'}
//clear():清空所有的元素;
//map2.clear()
console.log(map2)
//Map(0) {size: 0}
// 4.遍历map
//forEach(callback, [, thisArg]):通过forEach遍历Map;
map2.forEach((item, key) => {
console.log(item, key);
})
console.log(Object.prototype.toString.call(map2));//[object Map]
for(const item of map2){
console.log(item);//遍历出来三个数组,每个数组里面放着key和value
console.log(item[0], item[1]);//item[0]是key,item[1]是value
}
//遍历的同时进行结构
for(const [key, value] of map2){
console.log(key, value);
}
WeakMap
1 WeakMap的使用
108.PNG- 区别1:
WeakSet只能存放对象
WeakMap的key只能时对象,Map的key可以是对象或者普通数据类型
- 区别2:
<img src="img/110.PNG" alt="alt" style="zoom:50%;" />
map时强引用类型,就算obj=null,也不会销毁ox100. 如果换成了weakmap,就变成了弱引用,当obj=null的时候,ox100也会被销毁。
const obj = {name: "obj1"}
// 1.WeakMap和Map的区别二:
const map = new Map()
map.set(obj, "aaa")
const weakMap = new WeakMap()
weakMap.set(obj, "aaa")
// 2.区别一: 不能使用基本数据类型
// weakMap.set(1, "ccc")
// 3.常见方法
// get方法
console.log(weakMap.get(obj))//aaa
// has方法
console.log(weakMap.has(obj))//true
console.log(weakMap)
// delete方法
console.log(weakMap.delete(obj))//true
// WeakMap { <items unknown> }
console.log(weakMap) //因为weakMap不可以遍历
2 WeakMap的应用
109.PNG14_响应式原理中的WeakMap使用
响应式就是监听对象属性的改变,并且执行某些函数做出对应的响应,这个就是vue3响应式原理里面做的事情。
111.PNG// 应用场景(vue3响应式原理)
const obj1 = {
name: "why",
age: 18
}
function obj1NameFn1() {
console.log("obj1NameFn1被执行")
}
function obj1NameFn2() {
console.log("obj1NameFn2被执行")
}
function obj1AgeFn1() {
console.log("obj1AgeFn1")
}
function obj1AgeFn2() {
console.log("obj1AgeFn2")
}
const obj2 = {
name: "kobe",
age: 30,
address: "广州市"
}
function obj2NameFn1() {
console.log("obj1NameFn1被执行")
}
function obj2NameFn2() {
console.log("obj1NameFn2被执行")
}
function obj2AgeFn1() {
console.log("obj2AgeFn1")
}
function obj2AgeFn2() {
console.log("obj2AgeFn2")
}
/*
我们想要obj1.name属性改变的时候,执行obj1NameFn1和obj1NameFn2
我们想要obj1.age属性改变的时候,执行obj1AgeFn1和obj1AgeFn2
我们想要obj2.name属性改变的时候,执行obj2NameFn1和obj2NameFn2
我们想要obj2.age属性改变的时候,执行obj2AgeFn1和obj2AgeFn2
如何把数据之间通过某种数据结构关联到一起。
想到对应、映射关系。
*/
//weakmap的key只能时对象
// 1.创建WeakMap
const weakMap = new WeakMap()
// 2.收集依赖结构
// 2.1.对obj1收集的数据结构
const obj1Map = new Map()
obj1Map.set("name", [obj1NameFn1, obj1NameFn2]);
obj1Map.set("age", [obj1AgeFn1, obj1AgeFn2]);
weakMap.set(obj1, obj1Map)
// 2.2.对obj2收集的数据结构
const obj2Map = new Map()
obj2Map.set("name", [obj2NameFn1, obj2NameFn2]);
obj2Map.set("age", [obj2AgeFn1, obj2AgeFn2]);
weakMap.set(obj2, obj2Map)
// 3.如果obj1.name发生了改变
// Proxy/Object.defineProperty
obj1.name = "james";
const targetMap = weakMap.get(obj1);
const fns = targetMap.get("name")
fns.forEach(item => item())
/*
这里为什么要使用weakmap
是因为weakmap时弱引用
当我们想销毁obj1的时候,obj1 = null;
因为weakmap时弱引用,所以会被GC回收和销毁,如果是map的话,就不可以了
*/
112.PNG
网友评论