3

Javascript now has classes called WeakMap and WeakSet, where the keys are weakly referenced.

Why may instances of these not be iterated over, i.e. using WeakMap#entires?

Note: this isn't a duplicate question. The other one asks "how" and this asks "why".

Lucien
  • 776
  • 3
  • 12
  • 40
  • @bergi This question isn't a duplicate. The one you linked asks "how" and mine asks "why"- notice that the answers to the linked one don't explain "why". – Lucien Jun 24 '18 at 13:10
  • You use the weak structures you do not want to keep these objects alive, ie. you have them in a set if they're alive but you don't care whether they live or not. Iterating implies that you do care. There is a natural tension there. Allowing both at the same time would likely be a source of bugs. – arnt Jun 25 '18 at 09:01
  • @Lolums Sorry, wrong link. [This one](https://stackoverflow.com/questions/20508628/why-will-es6-weakmaps-not-be-enumerable) is more appropriate. – Bergi Jun 25 '18 at 09:22

2 Answers2

5

MDN explains this with

If they were, the list would depend on the state of garbage collection, introducing non-determinism.

But you probably wonder what that really means.

First of, garbage collection is non-deterministic. A JavaScript program may be garbage collected by the garbage collector at the sole discretion of the environment in which it runs.

Now imagine we have the following program:

const weakMap = new WeakMap();

const key1 = { data: 123 };
weakMap.set(key1, "value");
weakMap.set({ data: 456 }, "value");

for (const [key, value] of weakMap) {  // This does not actually work, of course
  console.log(`${key} is ${value}`);
}

What would you expect this program to produce?

We cannot tell because actually the object created by { data: 456 } would only be referenced in our map. So this entry is to be deleted by the garbage collector. But we cannot be sure (and it is even somewhat unlikely) that the garbage collector has already removed it from the map when iterating over it. On the other hand, it might indeed have already removed it.

This program would exhibit unpredictable behaviour and is therefore not allowed.

idmean
  • 14,540
  • 9
  • 54
  • 83
  • Looks like JavaScript will finally be getting a _true_ WeakReference implementation in the future! https://stackoverflow.com/a/58009243/2441655 This would enable an iterable WeakMap, by combining the two. (create an array of WeakRefs to each of the keys in the WeakMap, then iterate by iterating through keys and just combining each with the in-WeakMap value) – Venryx Nov 16 '19 at 09:55
  • "What would you expect this program to produce?" - I would expect to have strong references in the loop as 'key' and 'value' to the existed objects, so I could manage them. – rick-rick-rick Apr 09 '23 at 07:12
  • @rick-rick-rick Sure, but the GC might run before your for loop still. – idmean Apr 09 '23 at 08:31
0

According to the docs:

One difference to Map objects is that WeakMap keys are not enumerable (i.e., there is no method giving you a list of the keys). If they were, the list would depend on the state of garbage collection, introducing non-determinism.

Also, WeakMap#entries would create additional reference to the objects, thus preventing garbage collection and defeating WeakMap purpose.

trincot
  • 317,000
  • 35
  • 244
  • 286
pwolaq
  • 6,343
  • 19
  • 45