Dmi*_*rin 83 javascript ecmascript-harmony weakmap ecmascript-6
看看这个和这个 MDN页面,似乎地图和WeakMaps之间的唯一区别是WeakMaps缺少"大小"属性.但这是真的吗?他们之间有什么区别?
ksh*_*ish 85
当它们的键/值引用的对象被删除时,它们的行为都不同.让我们采取以下示例代码:
var map = new Map();
var weakmap = new WeakMap();
(function(){
var a = {x: 12};
var b = {y: 12};
map.set(a, 1);
weakmap.set(b, 2);
})()
Run Code Online (Sandbox Code Playgroud)
上述IIFE执行是没有办法,我们可以参考{x: 12}
和{y: 12}
了.垃圾收集器继续并从"WeakMap"中删除键b指针,并{y: 12}
从内存中删除.但是在"Map"的情况下,垃圾收集器不会从"Map"中删除指针,也不会{x: 12}
从内存中删除.
简介:WeakMap允许垃圾收集器执行其任务但不允许执行Map.
参考文献:http://qnimate.com/difference-between-map-and-weakmap-in-javascript/
Rax*_*ter 66
也许下一个解释对某些人来说会更清楚.
var k1 = {a: 1};
var k2 = {b: 2};
var map = new Map();
var wm = new WeakMap();
map.set(k1, 'k1');
wm.set(k2, 'k2');
k1 = null;
map.forEach(function (val, key) {
console.log(key, val); // k1 {a: 1}
});
k2 = null;
wm.get(k2); // undefined
Run Code Online (Sandbox Code Playgroud)
如您所见,k1
从内存中删除密钥后,我们仍然可以在地图中访问它.同时删除k2
WeakMap的键wm
也可以通过引用将其删除.
这就是为什么WeakMap没有像forEach这样的可枚举方法,因为没有WeakMap键列表,它们只是对另一个对象的引用.
Ber*_*rgi 47
经验丰富的JavaScript程序员会注意到,这个API可以用JavaScript实现,它有4个API方法共享的两个数组(一个用于键,一个用于值).这样的实施将有两个主要的不便之处.第一个是O(n)搜索(n是地图中的键数).第二个是内存泄漏问题.使用手动编写的映射,密钥数组将保留对密钥对象的引用,从而防止它们被垃圾回收.在本机WeakMaps中,对关键对象的引用保持"弱",这意味着它们不会阻止垃圾收集,以防没有对该对象的其他引用.
由于引用很弱,WeakMap键不可枚举(即没有方法为您提供键列表).如果是,那么列表将取决于垃圾收集的状态,引入非确定性.
[这就是他们没有size
财产的原因]
如果你想要一个密钥列表,你应该自己维护.还有一个ECMAScript提案 旨在引入简单的集合和映射,这些集合和映射不会使用弱引用并且可以枚举.
- 这将是"正常" Map
的.在MDN中没有提到,但在和声提案中,那些也有items
,keys
并且values
生成器方法和实现Iterator
接口.
Tre*_*xon 33
另一个区别:
WeakMaps的键仅为Object类型.不允许将原始数据类型作为键(例如,Symbol不能是WeakMap键).
字符串,数字或布尔值也不能用作WeakMap
键.A Map
可以使用原始值作为键.
w = new WeakMap;
w.set('a', 'b'); // Uncaught TypeError: Invalid value used as weak map key
m = new Map
m.set('a', 'b'); // Works
Run Code Online (Sandbox Code Playgroud)
小智 7
来自Javascript.info
Map——如果我们在常规 Map 中使用一个对象作为键,那么当 Map 存在时,该对象也存在。它占用内存,可能不会被垃圾收集。
let john = { name: "John" };
let array = [ john ];
john = null; // overwrite the reference
// john is stored inside the array, so it won't be garbage-collected
// we can get it as array[0]
Run Code Online (Sandbox Code Playgroud)
与此类似,如果我们在常规 Map 中使用一个对象作为键,那么当 Map 存在时,该对象也存在。占用内存,可能不会被垃圾回收
let john = { name: "John" };
let map = new Map();
map.set(john, "...");
john = null; // overwrite the reference
// john is stored inside the map,
// we can get it by using map.keys()
Run Code Online (Sandbox Code Playgroud)
WeakMap——现在,如果我们使用一个对象作为其中的键,并且没有对该对象的其他引用——它将自动从内存(和映射)中删除。
let john = { name: "John" };
let weakMap = new WeakMap();
weakMap.set(john, "...");
john = null; // overwrite the reference
// john is removed from memory!
Run Code Online (Sandbox Code Playgroud)
WeakMap
键必须是对象,而不是原始值。
let weakMap = new WeakMap();\n\nlet obj = {};\n\nweakMap.set(obj, "ok"); // works fine (object key)\n\n// can\'t use a string as the key\nweakMap.set("test", "Not ok"); // Error, because "test" is not an object\n
Run Code Online (Sandbox Code Playgroud)\n\n为什么????
\n\n让我们看下面的例子。
\n\nlet user = { name: "User" };\n\nlet map = new Map();\nmap.set(user, "...");\n\nuser = null; // overwrite the reference\n\n// \'user\' is stored inside the map,\n// We can get it by using map.keys()\n
Run Code Online (Sandbox Code Playgroud)\n\n\n\n\n如果我们使用一个对象作为常规 中的键
\n\nMap
,那么当 \nMap
存在时,该对象也存在。它占用内存并且可能不会被垃圾收集。\n
WeakMap
在这方面有着根本的不同。它不会阻止关键对象的垃圾收集。
let user = { name: "User" };\n\nlet weakMap = new WeakMap();\nweakMap.set(user, "...");\n\nuser = null; // overwrite the reference\n\n// \'user\' is removed from memory!\n
Run Code Online (Sandbox Code Playgroud)\n\n\n\n\n如果我们使用一个对象作为其中的键,并且没有其他\n对该对象的引用\xe2\x80\x93,它将自动从内存(以及映射)中删除。
\n
WeakMap
不支持迭代和方法keys(),values(),entries(),因此\xe2\x80\x99s无法从中获取所有键或值。
WeakMap 只有以下方法:
\n\n很明显,如果一个对象丢失了所有其他引用(例如上面代码中的“user”),那么它将被自动垃圾收集。但从技术上讲,它\xe2\x80\x99s 并没有在清理发生时准确指定。
\n\nJavaScript 引擎决定了这一点。它可以选择立即执行内存清理,或者等待更多删除发生后再进行清理。因此,从技术上讲,a 的当前元素计数WeakMap
是未知的。发动机可能已清理或未清理或部分清理。因此,不支持访问所有键/值的方法。
\n\n注意:- WeakMap 的主要应用领域是附加数据存储。就像缓存一个对象直到该对象被垃圾回收一样。
\n
归档时间: |
|
查看次数: |
23737 次 |
最近记录: |