Is it possible to create a "weak reference" in JavaScript?
Asked Answered
P

9

105

Is there any way in JavaScript to create a "weak reference" to another object? Here is the wiki page describing what a weak reference is. Here is another article that describes them in Java. Can anyone think of a way to implement this behavior in JavaScript?

Pasqualepasqueflower answered 5/11, 2008 at 21:15 Comment(5)
Just for reference; JavaScript doesn't have it, but ActionScript 3 (which is also ECMAScript) does. Check out the constructor parameter for Dictionary.Bina
Weak references are being discussed for ES6. Keep your eyes peeled.Oxa
*Official spec wiki/discussion at wiki.ecmascript.org/doku.php?id=strawman:weak_refs, currently “Last modified: 2013/02/02 22:25” *some other spec discussion at esdiscuss.org/topic/what-is-the-status-of-weak-references, currently last post “Sun Mar 3 11:56:05 PST 2013”Lowland
In most cases WRs are an attempt to solve the Lapsed Listener Problem, discussed here: [#43758717. If that question had a good answer I don't think there would be much need for WRs.Allin
@supercat I have posted an answer to the lapsed listener question.Allin
S
43

Update: Since July, 2020 some implementations (Chrome, Edge, Firefox and Node.js) has had support for WeakRefs as defined in the WeakRefs proposal, which is a "Stage 3 Draft" as of December 16, 2020.

There is no language support for weakrefs in JavaScript. You can roll your own using manual reference counting, but not especially smoothly. You can't make a proxy wrapper object, because in JavaScript objects never know when they're about to be garbage-collected.

So your ‘weak reference’ becomes a key (eg. integer) in a simple lookup, with an add-reference and remove-reference method, and when there are no manually-tracked references anymore then entry can be deleted, leaving future lookups on that key to return null.

This is not really a weakref, but it can solve some of the same problems. It's typically done in complex web applications to prevent memory leakage from browsers (typically IE, especially older versions) when there is a reference loop between a DOM Node or event handler, and an object associated with it such as a closure. In these cases a full reference-counting scheme may not even be necessary.

Sapienza answered 5/11, 2008 at 21:59 Comment(4)
I haven't carefully examined (or used) the code, but es-lab has a script providing basic WeakMap emulation. Aurora 6 (Mozilla) has a non-standard WeakMap implementation.Terrenceterrene
With ES6 this answer is no longer correct. See my answer below https://mcmap.net/q/103929/-is-it-possible-to-create-a-quot-weak-reference-quot-in-javascriptPesthouse
It's still correct, because ES6 WeakMaps aren't true weak references. WeakMaps accept objects as keys only, and the references to these objects are held weakly. See #32398229Pointless
I wrote a class to emulate a weak map and posted it here: https://mcmap.net/q/104023/-garbage-collected-cache-via-javascript-weakmapsBrooklynese
R
15

When running JS on NodeJS, you may consider https://github.com/TooTallNate/node-weak.

Retrad answered 11/8, 2012 at 2:2 Comment(0)
P
13

Update: September 2019

It is not possible to use weak references yet, but most likely soon it will be possible, as WeakRefs in JavaScript are Work In Progress. Details below.

Proposal

Proposal in now in Stage 3 which means that it has complete specification and that further refinement will require feedback from implementations and users.

The WeakRef proposal encompasses two major new pieces of functionality:

  • Creating weak references to objects with the WeakRef class
  • Running user-defined finalizers after objects are garbage-collected, with the FinalizationGroup class

Use cases

A primary use for weak references is to implement caches or mappings holding large objects, where it’s desired that a large object is not kept alive solely because it appears in a cache or mapping.

Finalization is the execution of code to clean up after an object that has become unreachable to program execution. User-defined finalizers enable several new use cases, and can help prevent memory leaks when managing resources that the garbage collector doesn't know about.

Source and further reading

https://github.com/tc39/proposal-weakrefs
https://v8.dev/features/weak-references

Pericranium answered 19/9, 2019 at 10:43 Comment(1)
Firefox Nightly has added experimental support for WeakRef. Here's an example implementation using it to create an iterable version of WeakSet: gist.github.com/seanlinsley/bc10378fd311d75cf6b5e80394be813dSchnorkle
G
5

2021 Update

WeakRef is now implemented in Chrome, Edge, and Firefox. Still waiting on Safari and some other holdouts.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakRef

May 2021 Update It's now available on Safari thus all major browsers. See above.

Geyer answered 3/1, 2021 at 16:38 Comment(0)
O
3

Finally they are here. Not yet implemented in browsers, but soon to be.

https://v8.dev/features/weak-references

Outrelief answered 10/7, 2019 at 8:30 Comment(0)
S
2

True weak references, no, not yet (but browser makers are looking at the subject). But here is an idea on how to simulate weak references.

You could build a cache which you drive your objects through. When an object is stored, the cache keeps a prediction of how much memory the object will take up. For some items, like storing images, this is straight forward to work out. For others this would be more difficult.

When you need an object, you then ask the cache for it. If the cache has the object, it is returned. If it is not there, then the item is generated, stored, and then returned.

The weak references are simulated by the cache removing items, when the total amount of predicted memory reaches a certain level. It will predict which items are least used based on how often they are retrieved, weighted by how long ago they were taken out. A 'calculation' cost could also be added, if the code that creates the item is passed into the cache as a closure. This would allow the cache to keep items which are very expensive to build or generate.

The deletion algorithm is key, because if you get this wrong then you could end up removing the most popular items. This would cause terrible performance.

As long as the cache is the only object with permanent references to the objects stored, then the above system should work pretty well as an alternative to true weak references.

Sortilege answered 3/9, 2011 at 7:58 Comment(8)
Isn't most of what you said irrelevant to weakrefs?Rudiment
@ErikAllik Most uses for weak references is to store large amounts of data, and delete it if you run out of space. I described a way to fake that, by automatically keeping track of memory yourself, and deleting items when they are no longer needed.Sortilege
@Sortilege -- the important use for weak references is not for caches but for event-handlers. I have some object that, while it exists, should observe some other event -- but I don't want the fact that it is in a notification-list to constitute a reference for the purposes of GC.Townsman
@Malvolio well I've used weak references successfully for caches in Java, and they work well.Sortilege
Weak references are nothing to do with caching. A weak reference means you want to keep track of something, but if there are no remaining references to the object being tracked, you allow it to be deleted.Irenairene
There's clearly a use case for building a cache using weak references for automatic expiry.Impearl
+1. Using weak references with caching makes sense when used in the way you describe here. Unfortunately this is not possible with JS, so the approach you detail seems like the best alternative, and possibly even better than using weak references as it gives more control, at the expense of requiring a more explicit implementation.Glaciate
Caching is the traditionally a top reason for weak references. The event handler DOM thing is only some IE explorer buggy thing.Dincolo
R
2

Using a caching mechanism to emulate a weak reference, as JL235 suggested above, is reasonable. If weak references would exist natively, you would observe a behavior like this:

this.val = {};
this.ref = new WeakReference(this.val);
...
this.ref.get(); // always returns val
...
this.val = null; // no more references
...
this.ref.get(); // may still return val, depending on already gc'd or not

Whereas with a cache you would observe:

this.val = {};
this.key = cache.put(this.val);
...
cache.get(this.key); // returns val, until evicted by other cache puts
...
this.val = null; // no more references
...
cache.get(this.key); // returns val, until evicted by other cache puts

As a holder of a reference, you should not make any assumptions about when it refers to a value, this is no different using a cache

Reynold answered 8/2, 2017 at 17:16 Comment(0)
P
-5

EcmaScript 6 (ES Harmony) has a WeakMap object. Browser support amongst modern browsers is pretty good (the last 3 versions of Firefox, chrome and even an upcoming IE version support it).

Pesthouse answered 17/2, 2015 at 17:37 Comment(3)
This isn't exactly the same. A WeakMap doesn't give weak references to objects-- it is not the values that are weak references in WeakMap, but the keys. The fact that weak references exist in the map is only a memory leak prevention mechanism, and is not observable to the user otherwise.Tricuspid
You're correct that it's the keys that are weak, not the values. But the whole purpose of using weak references is to allow garbage collection of the referenced object. The OP posted two links, the second of which is about adding an id to an object you can't extend, and in fact it recommends using WeakHashMap, the Java equivalent of JavaScript's WeakMap.Pesthouse
good luck using WeakMap to implement a weak reference since weakmap.get(new String('any possible key that has ever existed or ever will exist')) will always be undefined. Not useful. Down-voting!Shimmer
S
-6

http://www.jibbering.com/faq/faq_notes/closures.html

ECMAScript uses automatic garbage collection. The specification does not define the details, leaving that to the implementers to sort out, and some implementations are known to give a very low priority to their garbage collection operations. But the general idea is that if an object becomes un-referable (by having no remaining references to it left accessible to executing code) it becomes available for garbage collection and will at some future point be destroyed and any resources it is consuming freed and returned to the system for re-use.

This would normally be the case upon exiting an execution context. The scope chain structure, the Activation/Variable object and any objects created within the execution context, including function objects, would no longer be accessible and so would become available for garbage collection.

Meaning there are no weak ones only ones that no longer become available.

Shermy answered 5/11, 2008 at 21:28 Comment(2)
Avoiding reference cycles isn't the only reason to use weak references. They're very handy for object instance pooling/caching and so on.Rosiarosicrucian
Definition of WeakReference is not an of the question. Also as agree with comment above.Clabo

© 2022 - 2024 — McMap. All rights reserved.