La raccolta dei rifiuti e la gestione della memoria in JavaScript sono argomenti leggermente sconosciuti per la maggior parte degli sviluppatori, poiché di solito non eseguiamo esplicitamente alcuna operazione di gestione della memoria nella maggior parte dei linguaggi di programmazione. Tuttavia, è consigliabile (e sempre utile) sapere come funziona il ciclo di gestione della memoria e come vengono liberate le risorse occupate quando non sono più in uso.
Allocazione della memoria in JavaScript
In basso livello linguaggi di programmazione come C, gli sviluppatori devono occuparsi della memoria. Devono allocare o rilasciare manualmente la memoria utilizzando funzioni come calloc(), malloc(), realloc(), e gratuito(). In linguaggi di alto livello come JavaScript e Java, tuttavia, non è necessario allocare o deallocare manualmente la memoria; invece, è fatto dalla lingua stessa.
In JavaScript, quando crei un nuovo oggetto, non hai bisogno di alcun metodo speciale per allocare memoria per quell’oggetto. Allo stesso modo, quando si desidera distruggere quell’oggetto, non è necessario chiamare esplicitamente alcun metodo speciale per liberare memoria. JavaScript è lì per gestire da solo l’allocazione e la deallocazione della memoria.
Il processo di gestione della memoria in quasi tutti i linguaggi di alto livello è automatico, ma ciò non significa che gli sviluppatori siano liberi da preoccupazioni per quanto riguarda la gestione della memoria. Il modo in cui hai codificato qualcosa ha un impatto significativo sull’allocazione della memoria. Se il codice che hai scritto è di scarsa qualità, potrebbe causare perdite di memoria e alla fine le prestazioni dell’applicazione potrebbero risentirne. Quindi, diventare consapevoli delle tecniche di gestione della memoria e della garbage collection è davvero importante.
Prima di immergerci nella raccolta dei rifiuti, dobbiamo prima dare un’occhiata a come viene gestita la memoria.
Leggi: Strumento e librerie HTML, CSS e JavaScript
Cos’è il ciclo di vita della memoria JavaScript?
Il ciclo di vita della memoria descrive come viene gestita la memoria. Il processo è suddiviso in tre fasi. Innanzitutto, hai bisogno di memoria da allocare. Ogni volta che crei una nuova variabile e le assegni un valore, allocherà la memoria per quella variabile.
Il secondo passaggio consiste nell’utilizzare la memoria allocata per attività come operazioni di lettura o scrittura. Potresti voler leggere le proprietà di alcuni oggetti o modificarli in qualche modo.
Il terzo passaggio consiste nel deallocare la memoria per quell’oggetto. Potresti voler liberare la memoria quando quella variabile o quell’oggetto non è più necessario. Il terzo passaggio è fondamentale perché se non rilasci la memoria occupata del tuo programma, consumerà sempre più memoria dalla tua applicazione e provocherà l’arresto anomalo dell’applicazione.
La deallocazione della memoria a volte è un compito difficile nel processo del ciclo della memoria, indipendentemente dal fatto che venga eseguita manualmente o venga gestita dal linguaggio di programmazione stesso.
JavaScript Garbage Collection Esempi
Un linguaggio di programmazione moderno e di alto livello come JavaScript si occupa di tutti i passaggi che coinvolgono la gestione della memoria, dall’allocazione delle risorse fino al loro rilascio. Ma come si libera la memoria una volta che non è più necessaria? La nostra prossima sezione descrive il rilascio delle risorse allocate attraverso un processo chiamato raccolta dei rifiuti.
Come funziona Garbage Collection in JavaScript
Come abbiamo già discusso, il terzo passaggio nella gestione della memoria è un processo difficile. Come fa JavaScript a sapere quale memoria dovrebbe essere rilasciata? Quali strumenti vengono utilizzati dal Garbage Collector per rilasciare tali risorse?
Ci sono alcuni algoritmi e strumenti che il garbage collector usa per capirlo. Diamo un’occhiata ad alcune di queste strategie nella prossima sezione.
Leggi: Programmazione asincrona in JavaScript
Strategia del raccoglitore di rifiuti per il conteggio dei riferimenti
Questa strategia di Garbage Collection viene utilizzata per evidenziare le risorse che non hanno più riferimenti. Considera il seguente frammento di codice:
const obj = { name: ‘Bob’, country: 'United States', }; obj = 'You are reading the article on Garbage Collection';
Inizialmente, il obj l’oggetto contiene alcuni attributi di proprietà. In seguito, lo sviluppatore ha deciso di cambiare il obj oggetto per contenere un valore primitivo. Quindi ora, il primo obj oggetto non contiene alcun riferimento che punta ad esso, il che lo rende pronto per essere rivendicato per la raccolta dei rifiuti.
Ma non è così semplice.
C’è una strategia meno conosciuta di cui dovresti essere a conoscenza, chiamata dipendenza circolare. Lo sviluppatore probabilmente non ci ha mai pensato prima, perché JavaScript lo gestisce per te sotto il cofano.
Pensa a una situazione in cui due oggetti fanno riferimento l’uno all’altro. In tal caso, il garbage collector non sarebbe in grado di decidere quale rimuovere dalla memoria perché ognuno ha almeno un riferimento a un altro.
Per comprendere meglio, considera il seguente frammento di codice JavaScript:
var obj = { a: { b: ‘Hello’ } }; obj = 15.6; function callMe() { var obj = {}; var obj2 = {}; obj.a = obj2; obj2.a = obj; return obj; } callMe();
Il codice sopra mostra che l’oggetto obj fa riferimento obj2 e obj2 fa riferimento obj. Questo crea un ciclo.
Dopo che l’oscilloscopio è stato spostato fuori dalla funzione Chiamami(), il garbage collector non sarà in grado di liberare la memoria occupata da questi due oggetti perché contengono riferimenti l’uno all’altro. Ciò fa sì che il programma perda memoria.
Per superare questa situazione, JavaScript ha un’altra strategia di cui gli sviluppatori possono trarre vantaggio, come dettagliato nella sezione successiva.
L’algoritmo JavaScript mark-and-sweep
Il segna e spazza algoritmo è un famoso algoritmo utilizzato per la raccolta dei rifiuti ed è di gran lunga migliore dell’algoritmo della sezione precedente. Funziona in base al principio di determinare se l’oggetto può essere raggiunto dal radice. In JavaScript, puoi pensare a radice come un finestra oggetto in un browser Chrome; pensa a globale oggetto se sei su a Nodo.js app.
Questa strategia funziona come segue:
Innanzitutto, segna tutti i radice oggetti. Successivamente, visiterà tutti i riferimenti che possono essere raggiunti da questi radice oggetti. Ancora una volta, rivisita gli oggetti contrassegnati e contrassegna i loro riferimenti. Questo processo di visita e marcatura continua fino a quando non vengono visitati tutti i riferimenti raggiungibili.
Il Garbage Collector può ora identificare quali oggetti sono contrassegnati e quali no. Quindi, gli oggetti che non sono contrassegnati (sono chiamati irraggiungibile oggetti) vengono selezionati per la raccolta dei rifiuti e infine rimossi dalla memoria.
Leggi: OOP in JavaScript con Classi
Considerazioni finali sulla raccolta dei rifiuti in JavaScript
Questo tutorial per sviluppatori web era solo una panoramica delle strategie di raccolta dei rifiuti utilizzate in JavaScript. L’argomento è molto più complesso e non può essere spiegato in un solo articolo. Consiglio agli sviluppatori di saperne di più attraverso il documento MDN.
Anche il modo in cui uno sviluppatore codifica influisce sulla quantità di memoria che verrà allocata. Ecco perché è importante concentrarsi sulla scrittura del codice con le migliori pratiche e acquisire familiarità con le strategie di raccolta dei rifiuti e come liberare le risorse quando necessario. Esistono diversi strumenti e metodi sul mercato che possono aiutarti ad analizzare le perdite di memoria e altri problemi di prestazioni nel tuo programma.