È possibile creare un "riferimento debole" in javascript?


97

C'è un modo in javascript per creare un "riferimento debole" a un altro oggetto? Ecco la pagina wiki che descrive cos'è un riferimento debole. Ecco un altro articolo che li descrive in Java. Qualcuno può pensare a un modo per implementare questo comportamento in javascript?


4
I riferimenti deboli sono in discussione per ES6. Tieni gli occhi aperti.
Ryan Smith

2
* Wiki / discussione sulle specifiche ufficiali su wiki.ecmascript.org/doku.php?id=strawman:weak_refs , attualmente "Ultima modifica: 2013/02/02 22:25" * qualche altra discussione sulle specifiche su esdiscuss.org/topic/what -è-lo-stato-dei-riferimenti-deboli , attualmente l'ultimo post "Sun Mar 3 11:56:05 PST 2013"
Destiny Architect

Nella maggior parte dei casi i WR sono un tentativo di risolvere il problema dell'ascoltatore scaduto , discusso qui: [ stackoverflow.com/questions/43758217/… . Se quella domanda avesse una buona risposta, non credo che ci sarebbe molto bisogno di WR.
James,

Risposte:


39

Non c'è supporto linguistico per weakrefs in JavaScript. Puoi eseguire il rollio utilizzando il conteggio manuale dei riferimenti, ma non in modo particolarmente fluido. Non puoi creare un oggetto wrapper proxy, perché in JavaScript gli oggetti non sanno mai quando stanno per essere raccolti in modo garbage.

Quindi il tuo "riferimento debole" diventa una chiave (ad es. Intero) in una semplice ricerca, con un metodo di aggiunta e rimozione del riferimento, e quando non ci sono più riferimenti tracciati manualmente, la voce può essere eliminata, lasciando le ricerche future attive quella chiave per restituire null.

Questo non è realmente un weakref, ma può risolvere alcuni degli stessi problemi. Viene in genere eseguito in applicazioni Web complesse per prevenire perdite di memoria dai browser (in genere IE, in particolare versioni precedenti) quando è presente un loop di riferimento tra un nodo DOM o un gestore di eventi e un oggetto ad esso associato come una chiusura. In questi casi, uno schema completo di conteggio dei riferimenti potrebbe non essere nemmeno necessario.


2
Non ho esaminato attentamente (o utilizzato) il codice, ma es-lab ha uno script che fornisce l' emulazione di base di WeakMap . Aurora 6 (Mozilla) ha un'implementazione WeakMap non standard .
theazureshadow

2
Con ES6 questa risposta non è più corretta. Vedi la mia risposta sotto stackoverflow.com/a/28567560/745190
thelastshadow

9
È ancora corretto, perché ES6 WeakMaps non sono veri riferimenti deboli. Le mappe deboli accettano gli oggetti solo come chiavi e i riferimenti a questi oggetti sono tenuti debolmente. Vedere stackoverflow.com/questions/32397729/...
CodeManX

Ho scritto una lezione per emulare una mappa debole e l'ho pubblicata qui: stackoverflow.com/a/47017206/491553
Ryan Shillington


11

Aggiornamento: settembre 2019

Non è ancora possibile utilizzare riferimenti deboli, ma molto probabilmente presto sarà possibile, poiché i WeakRef in JavaScript sono in lavorazione. Dettagli di seguito.

Proposta

La proposta è ora nella fase 3, il che significa che ha una specifica completa e che un ulteriore perfezionamento richiederà feedback da implementazioni e utenti.

La proposta WeakRef comprende due nuove importanti funzionalità:

  • Creazione di riferimenti deboli agli oggetti con la classe WeakRef
  • Esecuzione di finalizzatori definiti dall'utente dopo che gli oggetti sono stati sottoposti a garbage collection, con la classe FinalizationGroup

Casi d'uso

Un utilizzo principale per i riferimenti deboli è l'implementazione di cache o mappature che contengono oggetti di grandi dimensioni, dove si desidera che un oggetto di grandi dimensioni non sia mantenuto in vita solo perché appare in una cache o in una mappatura.

La finalizzazione è l'esecuzione del codice da ripulire dopo che un oggetto è diventato irraggiungibile per l'esecuzione del programma. I finalizzatori definiti dall'utente abilitano diversi nuovi casi d'uso e possono aiutare a prevenire perdite di memoria durante la gestione di risorse di cui il Garbage Collector non è a conoscenza.

Fonte e ulteriori letture

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


1
Firefox Nightly ha aggiunto il supporto sperimentale per WeakRef. Ecco un esempio di implementazione che lo utilizza per creare una versione iterabile di WeakSet: gist.github.com/seanlinsley/bc10378fd311d75cf6b5e80394be813d
seanlinsley

3

Veri riferimenti deboli, no, non ancora (ma i produttori di browser stanno esaminando l'argomento). Ma ecco un'idea su come simulare riferimenti deboli.

Potresti costruire una cache in cui guidare i tuoi oggetti. Quando un oggetto viene archiviato, la cache mantiene una previsione della quantità di memoria occupata dall'oggetto. Per alcuni elementi, come l'archiviazione delle immagini, è facile risolverlo. Per altri questo sarebbe più difficile.

Quando hai bisogno di un oggetto, chiedilo alla cache. Se la cache contiene l'oggetto, viene restituito. Se non è presente, l'elemento viene generato, archiviato e quindi restituito.

I riferimenti deboli vengono simulati dalla cache rimuovendo gli elementi, quando la quantità totale di memoria prevista raggiunge un certo livello. Prevede quali elementi sono meno utilizzati in base alla frequenza con cui vengono recuperati, ponderati in base a quanto tempo fa sono stati estratti. È inoltre possibile aggiungere un costo di "calcolo", se il codice che crea l'elemento viene passato nella cache come chiusura. Ciò consentirebbe alla cache di conservare elementi molto costosi da costruire o generare.

L'algoritmo di cancellazione è fondamentale, perché se sbagli potresti finire per rimuovere gli elementi più popolari. Ciò causerebbe prestazioni terribili.

Finché la cache è l'unico oggetto con riferimenti permanenti agli oggetti memorizzati, il sistema sopra dovrebbe funzionare abbastanza bene come alternativa ai veri riferimenti deboli.


25
La maggior parte di quello che hai detto non è irrilevante per i weakrefs?
Erik Kaplun

22
@ JL235 - l'uso importante per i riferimenti deboli non è per le cache ma per i gestori di eventi. Ho qualche oggetto che, sebbene esista, dovrebbe osservare qualche altro evento, ma non voglio che il fatto che si trovi in ​​un elenco di notifiche costituisca un riferimento ai fini del GC.
Malvolio

7
I riferimenti deboli non hanno nulla a che fare con la memorizzazione nella cache. Un riferimento debole significa che vuoi tenere traccia di qualcosa, ma se non ci sono riferimenti rimanenti all'oggetto da tracciare, ne consenti l'eliminazione.
fabspro

8
C'è chiaramente un caso d'uso per la creazione di una cache utilizzando riferimenti deboli per la scadenza automatica.
Phil Freeman

5
La memorizzazione nella cache è tradizionalmente uno dei motivi principali per i riferimenti deboli. La cosa DOM del gestore di eventi è solo una cosa buggata da Explorer di IE.
axkibe


2

L'uso di un meccanismo di memorizzazione nella cache per emulare un riferimento debole, come suggerito sopra JL235 , è ragionevole. Se i riferimenti deboli esistessero in modo nativo, osserveresti un comportamento come questo:

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

Mentre con una cache osserverai:

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

Come detentore di un riferimento, non dovresti fare alcuna supposizione su quando si riferisce a un valore, non è diverso usare una cache



-4

EcmaScript 6 (ES Harmony) ha un oggetto WeakMap . Il supporto del browser tra i browser moderni è piuttosto buono (le ultime 3 versioni di Firefox, Chrome e persino una versione imminente di IE lo supportano).


29
Non è esattamente la stessa cosa. A WeakMapnon fornisce riferimenti deboli agli oggetti: non sono i valori a essere riferimenti deboli in WeakMap, ma le chiavi . Il fatto che esistano riferimenti deboli nella mappa è solo un meccanismo di prevenzione della perdita di memoria e non è altrimenti osservabile dall'utente.
EyasSH

1
Hai ragione sul fatto che sono le chiavi che sono deboli, non i valori. Ma l'intero scopo dell'utilizzo di riferimenti deboli è consentire la garbage collection dell'oggetto a cui si fa riferimento. L'OP ha pubblicato due collegamenti, il secondo dei quali riguarda l'aggiunta di un ID a un oggetto che non è possibile estendere, e infatti consiglia di utilizzare WeakHashMap, l'equivalente Java di JavaScript WeakMap.
thelastshadow

12
buona fortuna usando WeakMap per implementare un riferimento debole dal momento che weakmap.get(new String('any possible key that has ever existed or ever will exist'))sarà sempre essere undefined. Non utile. Voto negativo!
user3338098

-5

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

ECMAScript utilizza la garbage collection automatica. La specifica non definisce i dettagli, lasciando che siano gli implementatori a risolverli, e alcune implementazioni sono note per dare una priorità molto bassa alle loro operazioni di garbage collection. Ma l'idea generale è che se un oggetto diventa non riferibile (non avendo riferimenti rimanenti ad esso lasciati accessibili al codice in esecuzione) diventa disponibile per la garbage collection e in futuro verrà distrutto e tutte le risorse che sta consumando liberate e restituite al sistema per il riutilizzo.

Questo normalmente sarebbe il caso all'uscita da un contesto di esecuzione. La struttura della catena dell'ambito, l'oggetto di attivazione / variabile e tutti gli oggetti creati all'interno del contesto di esecuzione, inclusi gli oggetti funzione, non sarebbero più accessibili e quindi diventerebbero disponibili per la garbage collection.

Significa che non ci sono deboli solo quelli che non diventano più disponibili.


10
Evitare i cicli di riferimento non è l'unico motivo per utilizzare riferimenti deboli. Sono molto utili per il pooling / caching di istanze di oggetti e così via.
soffice

La definizione di WeakReference non è una questione. Anche come d'accordo con il commento sopra.
Yuri Yaryshev
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.