Map与WeakMap

Map对象用来保存键值对,并且能够记住键的原始插入顺序,任何对象或者原始值都可以作为键或者是值。

WeakMap对象同样用来保存键值对,对于键是弱引用的而且必须为一个对象,而值可以是任意的对象或者原始值。

Map

描述

Map对象类似于一个普通的键值对的Object对象,也是键值对的集合,但是他们之间有一些重要的区别:

描述 Map Object
意外的键 Map默认情况不包含任何键,只包含显式插入的键。 一个Object有一个原型, 原型链上的键名有可能和在对象上的设置的键名产生冲突。
键的类型 一个Map的键可以是任意值,包括函数、对象或任意基本类型。 一个Object 的键必须是一个String或是Symbol
键的顺序 Map中的key是有序的,当迭代的时候,一个Map对象以插入的顺序返回键值。 一个Object的键的迭代顺序需要通过键的类型与创建的顺序来确定。
键值数量 Map的键值对个数可以轻易地通过size属性获取。 Object的键值对个数只能手动计算。
迭代 Mapiterable的,所以可以直接被迭代。 迭代一个Object需要以某种方式获取它的键然后才能迭代。
性能 Map在频繁增删键值对的场景下表现更好。 Object在频繁添加和删除键值对的场景下未作出优化。

注:关于一个Object的键的迭代顺序问题,在ES6以后,对象保留了StringSymbol的创建顺序,当创建的对象仅有String或者Symbol时,迭代顺序与创建顺序相同,当对象中两种类型都存在时,String总是在前,当String可以被转换为Number时,这些键在迭代时处于最前,且会按照数字的顺序进行迭代。

属性与方法

  • Map.prototype.constructor: 返回构造函数。
  • Map.prototype.size: 返回Map对象的键值对的数量。
  • Map.prototype.clear(): 移除Map对象的所有键值对 。
  • Map.prototype.delete(key): 如果Map对象中存在该元素,则移除它并返回true,否则如果该元素不存在则返回 false
  • Map.prototype.entries(): 返回一个新的Iterator对象,它按插入顺序包含了Map对象中每个元素的[key, value]数组。
  • Map.prototype.forEach(callback[, thisArg]): 按插入顺序,为Map对象里的每一键值对调用一次callback函数,如果为forEach提供了thisArg,它将在每次回调中作为this值。
  • Map.prototype.get(key): 返回键对应的值,如果不存在,则返回undefined
  • Map.prototype.has(key): 返回一个布尔值,表示Map实例是否包含键对应的值。
  • Map.prototype.keys(): 返回一个新的Iterator对象,它按插入顺序包含了Map对象中每个元素的键。
  • Map.prototype.set(key, value): 设置Map对象中键的值,返回该Map对象。
  • Map.prototype.values(): 返回一个新的Iterator对象,它按插入顺序包含了Map对象中每个元素的值。
  • Map.prototype[@@iterator](): 返回一个新的Iterator对象,它按插入顺序包含了Map对象中每个元素的[key, value]数组。

示例

var m = new Map();

var stringKey = "s";
var objectKey = {}; m.set(stringKey, "stringValue");
m.set(objectKey, "objectValue"); console.log(m.size); // 2 console.log(m.get(stringKey)); // stringValue
console.log(m.get(objectKey)); // objectValue for (let [key, value] of m) {
console.log(key, value);
}
/*
s stringValue
{} objectValue
*/ var m2 = new Map([
["stringKey", "stringValue"],
[{}, "objectValue"]
]);
console.log(m2); // Map(2) {"stringKey" => "stringValue", {…} => "objectValue"} var m3 = new Map([
...m,
...m2,
["stringKey", "coverStringValue"],
[{}, "{} !== {}"],
[NaN, "NaN !== NaN But key(NaN) === key(NaN)"],
[NaN, "NaN !== NaN But key(NaN) === key(NaN)"],
]);
console.log(m3); // Map(6) {"s" => "stringValue", {…} => "objectValue", "stringKey" => "coverStringValue", {…} => "objectValue", {…} => "{} !== {}", NaN => "NaN !== NaN But key(NaN) === key(NaN)"}

WeakMap

描述

WeakMapkey只能是Object类型,原始数据类型不能作为keyWeakMap持有的是每个键对象的弱引用,这意味着在没有其他引用存在时垃圾回收能正确进行,WeakMap用于映射的key只有在其没有被回收时才是有效的,正由于弱引用,WeakMapkey是不可枚举的,没有方法能给出所有的key

简单来说,有时需要在某个对象上面存放一些对象,但是这会形成对于这个对象的引用,一旦不再需要这个对象,我们就必须手动删除这个引用,否则垃圾回收机制无法释放对象占用的内存,WeakMap的设计就是解决这个问题的,它的键所引用的对象都是弱引用,垃圾回收机制不将该引用考虑在内,因此,只要所引用的对象的其他引用都被清除,垃圾回收机制就会释放该对象所占用的内存,此时WeakMap里边所对应的键值都会消失,不需要手动删除引用。如果需要在对象上添加对象而又不想干扰垃圾回收机制的话,就可以使用WeakMap

属性与方法

  • WeakMap.prototype.constructor: 返回构造函数。
  • WeakMap.prototype.delete(key): 移除key的关联对象。
  • WeakMap.prototype.get(key): 返回key关联对象,没有key关联对象时返回undefined
  • WeakMap.prototype.has(key): 根据是否有key关联对象返回一个Boolean值。
  • WeakMap.prototype.set(key, value): 在WeakMap中设置一组key关联对象,返回这个 WeakMap对象。

内存回收实例

// WeakMap示例代码
var wm = new WeakMap();
var key = {};
wm.set(key, new Array(6 * 1024 * 1024)); // 存放一个大数组
console.log(wm.get(key)); // (6291456) [empty × 6291456]
key = null;
console.log(wm.get(key)); // undefined
// WeakMap内存回收实例
/** node --expose-gc **/ // 启动node环境 手动调用垃圾回收机制
global.gc(); // 首先调用一次垃圾回收
process.memoryUsage(); // 查看内存占用 heapUsed约2M
/*
{
rss: 21975040,
heapTotal: 4608000,
heapUsed: 2454040,
external: 1384318
}
*/
var wm = new WeakMap();
var key = {};
wm.set(key, new Array(6 * 1024 * 1024)); // 存放一个大数组
console.log(wm.get(key)); // (6291456) [empty × 6291456]
process.memoryUsage(); // heapUsed约53M
/*
{
rss: 73420800,
heapTotal: 55259136,
heapUsed: 53060600,
external: 1384408
}
*/
global.gc(); // 手动执行一次垃圾回收
process.memoryUsage(); // heapUsed约53M
/*
{
rss: 73302016,
heapTotal: 55259136,
heapUsed: 52637112,
external: 1384350
}
*/
key = null; // 解除引用
global.gc(); // 执行垃圾回收
process.memoryUsage(); // heapUsed约2M 内存已回收
/*
{
rss: 23142400,
heapTotal: 4923392,
heapUsed: 2674536,
external: 1384445
}
*/
console.log(wm.get(key)); // undefined
// Map示例代码 对比
var m = new Map();
var key = {};
m.set(key, new Array(6 * 1024 * 1024)); // 存放一个大数组
console.log(m.get(key)); // (6291456) [empty × 6291456]
key = null;
console.log(m.get(key)); // undefined
console.log(m); // Map(1) {{…} => Array(6291456)}
m.clear(); // 回收内存
console.log(m); // Map(0) {}
// Map内存回收实例 对比
/** node --expose-gc **/ // 启动node环境 手动调用垃圾回收机制
global.gc(); // 首先调用一次垃圾回收
process.memoryUsage(); // 查看内存占用 heapUsed约2M
/*
{
rss: 21856256,
heapTotal: 4608000,
heapUsed: 2460600,
external: 1384318
}
*/
var m = new Map();
var key = {};
m.set(key, new Array(6 * 1024 * 1024)); // 存放一个大数组
console.log(m.get(key)); // (6291456) [empty × 6291456]
process.memoryUsage(); // heapUsed约53M
/*
{
rss: 73744384,
heapTotal: 55521280,
heapUsed: 53703816,
external: 1384504
}
*/
global.gc(); // 手动执行一次垃圾回收
process.memoryUsage(); // heapUsed约53M
/*
{
rss: 73125888,
heapTotal: 55521280,
heapUsed: 53135936,
external: 1384350
}
*/
key = null; // 解除引用
global.gc(); // 执行垃圾回收
process.memoryUsage(); // heapUsed约53M 内存未回收
/*
{
rss: 73093120,
heapTotal: 55521280,
heapUsed: 52960672,
external: 1384350
}
*/
console.log(m.get(key)); // undefined // 此处是undefined,这是因为key值的改变,而在这个Map实例对象中依然存在 {} => Array 的键值对,且键值对为强引用,内存未回收
console.log(m); // Map(1) {{…} => Array(6291456)}
m.clear(); // 回收内存
global.gc(); // 执行垃圾回收
process.memoryUsage(); // heapUsed约2M 内存已回收
/*
{
rss: 22908928,
heapTotal: 5185536,
heapUsed: 2627064,
external: 1384350
}
*/
console.log(m); // Map(0) {}

每日一题

https://github.com/WindrunnerMax/EveryDay

参考

https://blog.csdn.net/c__dreamer/article/details/82182649
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Map
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/WeakMap

Map与WeakMap的更多相关文章

  1. Map 和 WeakMap 数据结构

    Map 和 WeakMap 是ES6 新增的数据结构 一.Map 它们本质与对象一样,都是键值对的集合,但是他们与 Object 对象主要的不同是,键可以是各种类型的数值,而Object 对象的键 只 ...

  2. Map和WeakMap的区别

    个人总结:在一个变量作用域中,如果结束到作用域结尾 } 的话,map中的引用会被垃圾回收机制回收的是weakmap ,map中的引用不会被垃圾回收机制回收的是map. 强引用:只要引用存在,垃圾回收器 ...

  3. ES6新增的Map和WeakMap 又是什么玩意?非常详细的解释

    上一篇文章讲了set和weakSet,这节咱就讲Map和weakMap是什么?这两篇文章并没有什么联系,主要知识用法类似而已.嘿嘿,是不是感觉舒服多了. 什么是Map 介绍什么是Map,就不得不说起O ...

  4. Map和WeakMap的方法和区别

    Map Map是一组键值对的结构,具有极快的查找速度. 一.构造函数不同 let map = new Map(); let weakmap = new WeakMap(); 二.内置函数不同 Map的 ...

  5. ES6新特性:Javascript中的Map和WeakMap对象

    Map对象 Map对象是一种有对应 键/值 对的对象, JS的Object也是 键/值 对的对象 : ES6中Map相对于Object对象有几个区别: 1:Object对象有原型, 也就是说他有默认的 ...

  6. ES6 中的 Set、Map 和 WeakMap

    Set 是 ES6 新增的有序列表集合,它不会包含重复项. Set 支持 add(item) 方法,用来向 Set 添加任意类型的元素,如果已经添加过则自动忽略: has(item) 方法用来检测 S ...

  7. es6学习笔记--新数据结构Set,Map以及WeakSet,WeakMap

    在javascript中,存储数据的方式大部分就是以数组或者对象形式存储的,es6出现了4种新集合Set,Map,WeakSet,WeakMap来存储数据,简化了编程. 集合--Set 类似于数组,但 ...

  8. map,set和weakmap,weakset

    概述 set和map属于es6的内容,今天在看书的时候遇到了,所以好好的总结一下,供以后开发时参考,相信对其他人也有用. 参考资料: mdn Keyed collections Map和WeakMap ...

  9. ES6 Set,WeakSet,Map,WeakMap

    1. Set Set是一个集合,里面的值都是唯一的,没有重复的.Set中可以是任何数据类型,并且添加数据时会进行严格比较,重复数据无法加入. 2. WeakSet 弱引用Set.只能存储对象,不能存储 ...

  10. 引用、浅拷贝及深拷贝 到 Map、Set(含对象assign、freeze方法、WeakMap、WeakSet及数组map、reduce等等方法)

    从引用聊到深浅拷贝,从深拷贝过渡到ES6新数据结构Map及Set,再到另一个map即Array.map()和与其类似的Array.flatMap(),中间会有其他相关话题,例如Object.freez ...

随机推荐

  1. 文心一言 VS 讯飞星火 VS chatgpt (185)-- 算法导论14.1 2题

    二.用go语言,对于图 14-1中的红黑树 T 和关键字 x.key 为35的结点x,说明执行 OS-RANK(T,x) 的过程. 文心一言: 在红黑树中,OS-RANK(T, x) 是一个操作,用于 ...

  2. JS - dom绑定函数中 return false 的作用

    1,可以阻止事件冒泡 2,可以阻止浏览器默认操作

  3. [转帖]JVM 输出 GC 日志导致 JVM 卡住,我 TM 人傻了

    https://www.jianshu.com/p/51380e04eab1 最近,我们升级了 Java 17.后来,我们的 k8s 运维团队为了优化我们的应用日志采集, 将我们所有 pod (你可以 ...

  4. [转帖]一文说清 Linux System Load

    https://zhuanlan.zhihu.com/p/447661302 双十一压测过程中,常见的问题之一就是load 飙高,通常这个时候业务上都有受影响,比如服务rt飙高,比如机器无法登录,比如 ...

  5. [转帖]MySQL Decimal 的实现方法

    码: 背景 数字运算在数据库中是很常见的需求, 例如计算数量.重量.价格等, 为了满足各种需求, 数据库系统通常支持精准的数字类型和近似的数字类型. 精准的数字类型包含 int, decimal 等, ...

  6. [转帖]Redhat 8 磁盘调度策略变化:NOOP改为NONE

    说明 在 redhat 4/5/6/7版本中的NOOP调度策略,从8开始修改为NONE,官方解释: none Implements a first-in first-out (FIFO) schedu ...

  7. [转帖]Elasticsearch 的 30 个调优最佳实践!

    Elasticsearch 的 30 个调优最佳实践! https://zhuanlan.zhihu.com/p/406264041 ES 发布时带有的默认值,可为 es 的开箱即用带来很好的体验.全 ...

  8. [转帖]018 磁盘 IO 性能监控 / 压测工具 (sar、iotop、fio、iostat)

    https://my.oschina.net/u/3113381/blog/5465063   1 sar 命令查看当前磁盘 IO 读写 sar(System Activity Reporter 系统 ...

  9. 结论&定理大全

    定理 1:包含 \(0\) 与 \(2^k-1\) 的按位与或空间和 \(k\) 个点的有传递性的有向图形成双射 证明: 空间->传递闭包:对于任意两个位 \(i,j\),若某个数包含 \(i\ ...

  10. NOI2023 游记

    不完全按时间顺序写.记录 NOI 的一些琐事. 从 XDFZ 坐大巴 5 个小时来到成七.第一眼看到的是一个放着 NOI 牌子的台阶,还有一个签名墙.好像在我们之前到的人不太多? 用中英双语签名(冷月 ...