@@ -983,6 +983,19 @@ wm.get(key)
983
983
984
984
上面代码中,键值` obj ` 是正常引用。所以,即使在 WeakMap 外部消除了` obj ` 的引用,WeakMap 内部的引用依然存在。
985
985
986
+ ### WeakMap 的语法
987
+
988
+ WeakMap 与 Map 在 API 上的区别主要是两个,一是没有遍历操作(即没有` key() ` 、` values() ` 和` entries() ` 方法),也没有` size ` 属性。因为没有办法列出所有键名,某个键名是否存在完全不可预测,跟垃圾回收机制是否运行相关。这一刻可以取到键名,下一刻垃圾回收机制突然运行了,这个键名就没了,为了防止出现不确定性,就统一规定不能取到键名。二是无法清空,即不支持` clear ` 方法。因此,` WeakMap ` 只有四个方法可用:` get() ` 、` set() ` 、` has() ` 、` delete() ` 。
989
+
990
+ ``` javascript
991
+ const wm = new WeakMap ();
992
+
993
+ // size、forEach、clear 方法都不存在
994
+ wm .size // undefined
995
+ wm .forEach // undefined
996
+ wm .clear // undefined
997
+ ```
998
+
986
999
### WeakMap 的示例
987
1000
988
1001
WeakMap 的例子很难演示,因为无法观察它里面的引用会自动消失。此时,其他引用都解除了,已经没有引用指向 WeakMap 的键名了,导致无法证实那个键名是不是存在。
@@ -1014,32 +1027,37 @@ undefined
1014
1027
> let wm = new WeakMap ();
1015
1028
undefined
1016
1029
1030
+ // 新建一个变量 key,指向一个 5*1024*1024 的数组
1017
1031
> let key = new Array (5 * 1024 * 1024 );
1018
1032
undefined
1019
1033
1034
+ // 设置 WeakMap 实例的键名,也指向 key 数组
1035
+ // 这时,key 数组的引用计数为 2,
1036
+ // 变量 key 引用一次,WeakMap 的键名引用第二次
1020
1037
> wm .set (key,1 );
1021
1038
WeakMap {}
1022
1039
1023
1040
> global .gc ();
1024
1041
undefined
1025
1042
1026
- // 可以看到,增加数组key之后,heapUsed增加到45M了;
1043
+ // 这时内存占用 heapUsed 增加到 45M 了
1027
1044
> process .memoryUsage ();
1028
1045
{ rss: 67538944 ,
1029
1046
heapTotal: 7376896 ,
1030
1047
heapUsed: 45782816 ,
1031
1048
external: 8945 }
1032
1049
1033
- // 清除外界对key的引用,但没有手动清除WeakMap对key的引用
1050
+ // 清除变量 key 对数组的引用,
1051
+ // 但没有手动清除 WeakMap 实例的键名对数组的引用
1034
1052
> key = null ;
1035
1053
null
1036
1054
1037
1055
// 再次执行垃圾回收
1038
1056
> global .gc ();
1039
1057
undefined
1040
1058
1041
- // heapUsed 4M左右 ,
1042
- // 可以看到WeakMap对key的引用没有阻止gc对key所占内存的回收;
1059
+ // 内存占用 heapUsed 变回 4M 左右 ,
1060
+ // 可以看到 WeakMap 的键名引用没有阻止 gc 对内存的回收
1043
1061
> process .memoryUsage ();
1044
1062
{ rss: 20639744 ,
1045
1063
heapTotal: 8425472 ,
@@ -1049,19 +1067,6 @@ undefined
1049
1067
1050
1068
上面代码中,只要外部的引用消失,WeakMap 内部的引用,就会自动被垃圾回收清除。由此可见,有了 WeakMap 的帮助,解决内存泄漏就会简单很多。
1051
1069
1052
- ### WeakMap 的语法
1053
-
1054
- WeakMap 与 Map 在 API 上的区别主要是两个,一是没有遍历操作(即没有` key() ` 、` values() ` 和` entries() ` 方法),也没有` size ` 属性。因为没有办法列出所有键名,这个键名是否存在完全不可预测,跟垃圾回收机制是否运行相关。二是无法清空,即不支持` clear ` 方法。因此,` WeakMap ` 只有四个方法可用:` get() ` 、` set() ` 、` has() ` 、` delete() ` 。
1055
-
1056
- ``` javascript
1057
- const wm = new WeakMap ();
1058
-
1059
- // size、forEach、clear 方法都不存在
1060
- wm .size // undefined
1061
- wm .forEach // undefined
1062
- wm .clear // undefined
1063
- ```
1064
-
1065
1070
### WeakMap 的用途
1066
1071
1067
1072
前文说过,WeakMap 应用的典型场合就是 DOM 节点作为键名。下面是一个例子。
0 commit comments