سؤال

ECMAScript 6 introduces weak maps, available in Node.JS v0.11.3 with the --harmony flag. Consider the following.

let weakMap = WeakMap();
let key = [];
let rubbish = 'fish cans';

weakMap.set(key, rubbish);
rubbish = 'empty bottle';

// Prints "fish cans"
console.log(weakMap.get(key));

I was under the impression that, for weak maps, the reference from the key to the value is weak, so that if the only reference to the value is the key, then the value can no longer be accessed.

Why then is the value 'fish cans' still accessible and not garbage collected? The variable rubbish no longer references it, and the reference from key to 'fish cans' is weak, i.e. non-existant from the point of view of the garbage collector. What am I missing?

هل كانت مفيدة؟

المحلول

The weak part is about the keys, not the values. From the current draft:

WeakMap are intended to provide a mechanism for dynamically associating state with an object in a manner that does not “leak” memory resources if, in the absence of the WeakMap, the object otherwise became inaccessible and subject to resource reclamation by the implementation’s garbage collection mechanisms.

Say you have a DOM element and want to associate some data with it and use a WeakMap for that: weakMap.set(domElement, data);. When the DOM element gets deleted then the entry in the weak map gets deleted too.

On the other hand you would not want the data to be deleted as long the DOM element exists, just because there is no other reference to it outside the weak map.

Apart from that 'fish cans' is a primitive type and as such not subject to the garbage collection.

نصائح أخرى

Why then is the value 'fish cans' still accessible and not garbage collected? The variable rubbish no longer references it, and the reference from key to 'fish cans' is weak, i.e. non-existant from the point of view of the garbage collector. What am I missing?

The variable rubbish never was the one that needed to reference it. The association (reference) from the key to the value still exists as long as the key is not collected. The weak reference, which the GC cannot see, is the one from the map to the key/value pair (the one which would make the map enumerable). Yet your key still exists, and you can get every value that you stored for it in the map:

var map = WeakMap(),
    key = [];

map.set(key, 'fish cans');
console.log(map.get(key)); // Prints "fish cans"

To demonstrate the weakness, you'd have to use the following:

var map = WeakMap(),
    key = [];

map.set(key, 'fish cans');
// map.size == 1
key = null;
// map.size == 0 - the fish cans got garbage-collected together with the key
map.get(???) // impossible now

I am trying to understand this as well. I think the paragraph said like:

var key={a:1};
var wm=new WeakMap();


wm.set(key,"value");
wm.get(key); //you can get "value";

key=undefined;
console.log(wm.get(key));//error.original key have no longer existed. so "value" is not longer existed as well.

Due to WeakMap has no way to retrieve the keys, you have no way to get that "value" any more.

if we use Map(), due to has keys(),entries(), although the variable key lost reference, "value" still can be retrieved.

var key={a:1};
var m=new Map();


m.set(key,"value");
console.log(m.keys().next());; //you can get "value";

key=undefined;
console.log(m.get(m.keys().next().value));//you can get "value";

Conclusion:

If object key of WeakMap have lost its reference, this key and value will be garbage collected as well(because logically inaccessible). This way can prevent memory leak.

If object key of Map have lost its reference, this key and value will be still available until you deleted or cleared. So you need to be aware of memory leak during development

Just find a link about understanding weakmap and its use-cases: http://ilikekillnerds.com/2015/02/what-are-weakmaps-in-es6/

I'm adding this answer to address/clarify the following point:

The initial value of the variable 'rubbish' was never mutated; all you accomplished on rubbish = 'empty bottle'; was to associate the alias rubbish to a different value. Hence even after rubbish = 'empty bottle'; was executed, the weakMap entry with key 'key' still has a value associated with it that references the original value of rubbish.

Then to make the value lose its association with the key, you should change value of the key variable (as already noted in @Bergi's answer).

Note that key.push("whatever"); does not amount to a change. However, key = []; repeated again would do as well as key = null;. Generally, any reassignment will amount to the desired change.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top