一, Map
Map 类似于 Object(对象), 可用来存储键值对, 但需要通过 SameValueZero 算法保持键的唯一性. 与 Set 一样, 在使用之前也得要实例化, 如下代码所示, 构造函数 Map()中的参数也是一个可选的可迭代对象, 但此对象得是键值对的集合或两列的二维数组.
- new Map(); //Map(0) {
- }
- new Map([["name", "strick"], ["age", 28]]); //Map(2) {
- "name" => "strick", "age" => 28
- }
1)属性和方法
Map 比 Set 多一个读取方法: get(), 并且写入方法改成了 set(), 其它的属性和方法在功能上基本都一致, 只是有些参数在含义上略有不同, 例如 delete()的参数表示键而不是值. 方法的具体使用, 可参加下面的代码.
- var people = new Map();
- // 写入和读取
- people.set("name", "strick").set("age", 28); //Map(2) {"name" => "strick", "age" => 28}
- people.get("name"); //"strick"
- people.size; //2
- // 遍历
- [...people.keys()]; //["name", "age"]
- [...people.values()]; //["strick", 28]
- [...people.entries()]; //[["name", "strick"], ["age", 28]]
- /*
- "strick" "name" Map(2) {"name" => "strick", "age" => 28}
- 28 "age" Map(2) {"name" => "strick", "age" => 28}
- */
- people.forEach(function(value, index, map) {
- console.log(value, index, map);
- });
- // 移除
- people.delete("name")
- people.has("name"); //false
- people.clear();
- people.has("age"); //false
2)比较对象
本节开篇就提到 Map 和 Object 很类似, 但其实两者之间还是有一些很重要的区别, 具体如表 10 所列.
表 10 Map 和 Object 的对比
不同点 | Map | Object |
键 | 所有类型,甚至包括 NaN | 字符串或 Symbol 类型 |
可迭代对象 | 是 | 否 |
尺寸 | 通过 size 属性得到 | 需要手动计算 |
原型 | 无 | 有 |
写入 | set() 方法 | 等号运算符 |
读取 | get() 方法 | 成员访问运算符(点号或方括号) |
移除 | delete() 或 clear() 方法 | delete 运算符 |
枚举顺序 | 根据键值对的添加顺序 | 依照 ES6 的新规则 |
二, WeakMap
WeakMap 是 Map 的变体, 也是键值对的集合, 但它的键必须是弱引用的对象, 并且不可枚举, 而值没有限制, 还是保持任意类型. 当 WeakMap 的键所指的对象不再被引用时, 其键和值将被 GC 自动回收.
1)创建和方法
WeakSet 也需要像 Map 那样实例化 (如下代码所示), 但没有 Map 的 size 属性, 并且只包含 Map 中的四个方法: set(),get(),has() 和 delete(), 诸如清空和遍历相关的方法都是不存在的.
- var weak = new WeakMap(),
- arr = [1];
- weak.set(arr, 10); //WeakMap {Array(1) => 10}
- weak.get(arr); //10
- weak.has(arr); //true
- weak.delete(arr);
- weak.has(arr); //false
2)用途
WeakMap 的主要优势在于不干扰垃圾收集, 从而能够有效的防止内存泄漏. 它适用于隐藏信息, 存储 DOM 节点等场景. 下面是一个隐藏信息的示例, privates 变量是一个 WeakMap, 它的键是当前实例化的 People 对象, 存储的私有数据是一个对象, 两个原型方法分别用于写入和读取 name 属性.
- var people = (function() {
- var privates = new WeakMap();
- function People() {
- privates.set(this, {}); // 初始化私有数据
- }
- People.prototype.setName = function(name) {
- privates.get(this).name = name; // 写入
- };
- People.prototype.getName = function() {
- return privates.get(this).name; // 读取
- };
- return new People();
- })();
- people.setName("strick");
- people.getName(); //"strick"
这种存储方式不仅能让数据保持私有状态, 并且当与之关联的对象实例被销毁后, 这些私有数据将被 GC 一并删除, 从而释放内存.
下面是另一个存储 DOM 节点的示例, node 变量是一个 WeakMap, 它的键是文档中的 < div > 元素(即 DOM 的一个节点), 在该元素的事件处理程序中可更新 digit 属性. 当从文档中移除该元素时, 与之关联的数据也会随之被删除.
- <div id="container"></div>
- <script>
- var container = document.getElementById("container");
- var node = new WeakMap();
- node.set(container, { digit: 0 });
- container.addEventListener("click", function() {
- var current = node.get(this);
- current.digit++;
- node.set(this, current);
- },
- false
- );
- </script>
来源: https://www.cnblogs.com/strick/p/10314395.html