📝个人主页:爱吃炫迈
💌系列专栏:数据结构与算法
🧑💻座右铭:道阻且长,行则将至💗
文章目录
- 🌸Map
- key
- 创建map的其他方式
- Map常用方法
- Map结构原生提供三个遍历器生成函数和一个遍历方法
- Map和Object的区别
- 🌸WeakMap
- WeakMap常用方法
- WeakMap设计目的
- 强引用,弱引用
- 🌸总结
🌸Map
Map是一个键值对形式的集合,类似object,区别是Map允许任何的键(key)
key
举例一些key:
const map = new Map();
let obj = {
name: "jack",
age: 18,
};
map.set("1", "字符串");
map.set(2, "数字");
map.set(["3"], "数组");
map.set(obj, "对象");
map.set(true, "布尔值");
console.log(map);
结果如下:
注意
:在object中无法使用对象作为键使用,但是在map中对象是可以作为key使用
创建map的其他方式
创建map的时候,可以传入一个带有键值对的数组或者可迭代对象进行初始化
代码演示:
const map = new Map([
["a", 1],
["b", 2],
["c", 3],
]);
console.log(map);
const obj = {
name: "jack",
age: "12",
};
const map = new Map(Object.entries(obj));
console.log(map);
Map常用方法
new Map() | 创建map |
---|---|
map.set(key,value) | 存储键值对 |
map.get(key) | 根据key获取value,没有返回undefined |
map.has(key) | 是否存在key,存在返回true,反之为false |
map.delete(key) | 根据key删除指定项 |
map.clear() | 清空map |
map.size | 返回长度 |
代码演示:
const map = new Map();
map.set("1", "字符串");
map.set(2, "数字");
//等价于
map.set("1", "字符串").set(2, "数字");
map.get("1"); //字符串
map.get(2); //数字
map.has("1"); //true
map.has(2); //true
map.delete("1");
map.get("1"); //undefined
console.log(map.size);//1
注意
:根据上述代码我们发现map与对象不同,map的键不会被转成字符串,键保存是什么类型,get就是什么类型
Map结构原生提供三个遍历器生成函数和一个遍历方法
map.keys() | 遍历返回所有的key |
---|---|
map.values() | 遍历返回所有的value |
map.entries() | 遍历返回数组,以“key:value”的形式 |
forEach | 遍历Map所有成员 |
代码演示:
const map = new Map();
map.set("1", "字符串").set(2, "数字");
console.log(map.keys());
// 输出:{ '1', 2 }
console.log(map.values());
// 输出:{ '字符串', '数字' }
console.log(map.entries());
// 输出:{ [ '1', '字符串' ], [ 2, '数字' ] }
map.forEach((value, key, map) => {
console.log(`${key}:${value}`);
});
/**
* 输出:
* 1:字符串
* 2:数字
*/
Map和Object的区别
Map | Object | |
---|---|---|
意外的键 | Map默认情况下不包含任何键,只包含显式插入的键 | Object有一个原型,原型链上的键名有可能和自己在对象上设置的键名产生冲突 |
键的类型 | Map的键可以是任意值,包含函数、对象或任意基本类型 | Object的键必须是String或Symbol |
键的顺序 | Map中key是有序的。因此,当迭代的时候,Map对象以插入的顺序返回键值 | Object的键是无序的 |
Size | Map键值对的个数可以轻易地通过size属性获取 | Object的键值对个数只能手动计算 |
迭代 | Map是可迭代的,所以可以直接被迭代 | 迭代Object需要以某种方式获取它的键然后才能迭代 |
性能 | 在频繁增删键值对的场景下表现良好 | 在频繁增删键值对的场景下未作出优化 |
🌸WeakMap
WeakMap对象也是一组键值对的集合,其中键是弱引用的。其键必须是对象,原始数据类型不能作为key值,而值可以是任意的。
WeakMap常用方法
new WeakMap() | 创建WeakMap |
---|---|
WeakMap.set(key,value) | 存储键值对 |
WeakMap.get(key) | 根据key获取value,没有返回undefined |
WeakMap.has(key) | 是否存在key,存在返回true,反之为false |
WeakMap.delete(key) | 根据key删除指定项,删除成功返回true,反之返回false |
代码演示:
const weakmap = new WeakMap();
let m = { m: 1 };
let n = { n: 2 };
weakmap.set(m, "1");
weakmap.set(n, 2);
// 等价于
weakmap.set(m, "1").set(n, 2);
weakmap.get(m); //"1"
weakmap.get(n); //2
weakmap.has(m); //true
weakmap.has(s); //s is not defined
weakmap.delete(m);
weakmap.get(m); //undefined
WeakMap结构如下:
WeakMap设计目的
- 有时想在某个对象上存放一些数据,但是这会形成对于这个对象的引用。一旦不再需要这两个对象,就必须手动删除这个引用,否则垃圾回收机制就不会是的对象占用的内存。
- 而WeakMap的键名所引用的对象都是弱引用,即垃圾回收机制不将该引用考虑在内。因此,只需要引用的对象的其他引用都被清除,垃圾回收机制就会释放的该对象所占用的内存。也就是说,一旦不再需要,WeakMap里面的键名和所对应的键值对会自动消失,不用手动删除引用。
此时有点迷迷,强引用和弱引用又是什么鬼
强引用,弱引用
再来解释一下强引用和弱引用:
强引用:A牵着一条狗,他们之间通过狗链连着
弱引用:B指着A牵的狗,说:嘿,那有条狗,B指向那条狗,但他们之间没有是绑在一起的东西
当A放开狗链,无论B是不是还指着,狗都会跑掉(被垃圾回收器回收)
当B不再指着那条狗,狗还被A牵着,不会影响它是否跑掉
妙啊,直接悟了
悟了也得看下面的解释,不然我白写了
-
强引用:将一个引用类型数据通过变量/常量保存,这个变量/常量就是强引用。
-
特点: 不会被垃圾回收器回收,可能导致内存无法释放,造成内存泄漏。
-
方法:将全部引用该对象的变量关系都设置为null,这个对象就会被垃圾回收器回收。
var obj = { x: 1, y: 2 };
// 只要访问obj对象(或者任何其他引用指向该对象),这个对象就不会被垃圾回收
obj = null;
// obj设为null,obj就会被被垃圾回收器回收
-
弱引用:没有通过变量/常量和引用地址进行联系,有着更短暂的生命周期。
-
特点: 会时刻被垃圾回收器回收,不会导致内存泄漏
-
方法: WeakMap和WeakSet
let wm = new WeakMap();
let wobj = { x : 1 };
wm.set( wobj, '2' );
wobj = null;
// 说明:wobj为null后,键不存在,即为弱引用,{ x : 1 } 会被垃圾回收器回收
🌸总结
- Map数据结构。它类似于对象,也是键值对的集合,但是==“键”的范围不限于字符串,各种类型的值(包括对象)都可以当做键==。
- WeakMap结构与Map结构类似,也是用于生成键值对的集合。但是WeakMap只接受对象作为键名(null除外),不接受其他类型的值作为键名。而且WeakMap的键名所指向的键名不计入垃圾回收机制。
希望我的文章对你学习Map和WeakMap有所帮助!