Empfohlenes Tutorial: „JavaScript-Video-Tutorial“
Ich habe kürzlich einige Interviewrezensionen gesehen, und viele davon wurden vom Interviewer gebeten, über den JS-Garbage-Collection-Mechanismus zu sprechen Fragen und erklären Er hat kürzlich einige verwandte Artikel über den JS-Garbage-Collection-Mechanismus gesehen und hat im Interesse des B-Grids nebenbei gefragt.
Ich habe kürzlich einen ausländischen Artikel gesehen, in dem es um die JS-Garbage Collection ging. Ich dachte, er sei klar erklärt und hoffe, dass er für Sie hilfreich sein wird.
Speicherverwaltung in JavaScript erfolgt automatisch und unsichtbar. Wir erstellen primitive Typen, Objekte, Funktionen ... die alle Speicher benötigen.
Was passiert, wenn etwas nicht mehr benötigt wird? Wie findet und bereinigt die JavaScript-Engine es?
Das Hauptkonzept der Speicherverwaltung in JavaScript ist die Erreichbarkeit.
Einfach ausgedrückt sind „Erreichbarkeits“-Werte jene Werte, die auf irgendeine Weise zugänglich oder nutzbar sind und garantiert im Speicher gespeichert werden.
1. Es gibt einen grundlegenden Satz von inhärent erreichbaren Werten, die aus offensichtlichen Gründen nicht gelöscht werden können. Zum Beispiel:
Lokale Variablen und Parameter der lokalen Funktion
Variablen und Parameter anderer Funktionen in der aktuellen verschachtelten Aufrufkette
Globale Variablen
Es gibt auch einige andere, interne
Diese Werte werden Wurzeln genannt.
2. Jeder andere Wert gilt als zugänglich, wenn die Referenz oder Referenzkette vom Stamm aus darauf zugreifen kann.
Wenn es beispielsweise ein Objekt in einer lokalen Variablen gibt und dieses Objekt eine Eigenschaft hat, die auf ein anderes Objekt verweist, dann gilt das Objekt als erreichbar, und diejenigen, auf die es verweist, sind ebenfalls zugänglich. Detaillierte Beispiele sind wie folgt.
In der JavaScript-Engine gibt es einen Hintergrundprozess namens Garbage Collector, der alle Objekte überwacht und diejenigen löscht, auf die nicht zugegriffen werden kann.
Hier ist das einfachste Beispiel:
// user 具有对象的引用 let user = { name: "John" };
Hier stellt der Pfeil eine Objektreferenz dar. Die globale Variable "user"
verweist auf das Objekt {name: "John"
(der Kürze halber nennen wir es “user”
引用对象 {name:“John”}
(为了简洁起见,我们将其命名为John)。John 的 “name”
属性存储一个基本类型,因此它被绘制在对象中。
如果 user
的值被覆盖,则引用丢失:
user = null;
现在 John 变成不可达的状态,没有办法访问它,没有对它的引用。垃圾回收器将丢弃 John 数据并释放内存。
现在让我们假设我们将引用从 user
复制到 admin
:
// user具有对象的引用 let user = { name: "John" }; let admin = user;
现在如果我们做同样的事情:
user = null;
该对象仍然可以通过 admin
全局变量访问,所以它在内存中。如果我们也覆盖admin
,那么它可以被释放。
现在来看一个更复杂的例子, family 对象:
function marry (man, woman) { woman.husban = man; man.wife = woman; return { father: man, mother: woman } } let family = marry({ name: "John" }, { name: "Ann" })
函数 marry
John
"name"
-Eigenschaft speichert einen primitiven Typ, sodass er in das Objekt gezeichnet wird. Wenn der Wert von user
überschrieben wird, geht die Referenz verloren: delete family.father; delete family.mother.husband;
Jetzt ist
Johnnicht mehr erreichbar, es gibt keine Möglichkeit, darauf zuzugreifen, und es gibt keinen Verweis darauf. Der Garbage Collector verwirft die
John-Daten und gibt den Speicher frei.
Zwei ReferenzenNehmen wir nun an, wir kopieren die Referenz vonuser
nach admin
:family = null;
rrreeeDas Objekt kann immer noch übergeben werden admin Zugriff auf die globale Variable, sodass sie im Speicher liegt. Wenn wir auch admin
überschreiben, kann es freigegeben werden.
Zusammenhängende ObjekteSehen Sie sich nun ein komplexeres Beispiel an, das Familienobjekt:
rrreeeDie Funktion marry
„verheiratet“ zwei Objekte, indem sie ihnen Referenzen zueinander gibt, und gibt ein enthaltendes A new zurück Objekt für beide Objekte.
Resultierende Speicherstruktur:
Bisher sind alle Objekte zugänglich.
Jetzt löschen wir beide Referenzen:
rrreee🎜🎜 Das bloße Löschen einer dieser beiden Referenzen reicht nicht aus, da alle Objekte weiterhin zugänglich sind. 🎜🎜Aber wenn wir beide entfernen, dann können wir sehen, dass 🎜John🎜 keine eingehende Referenz mehr hat: 🎜🎜🎜🎜🎜Die ausgehende Referenz spielt keine Rolle. Nur das übergebene Objekt macht das Objekt zugänglich, daher ist 🎜John🎜 jetzt nicht mehr zugänglich und alle unzugänglichen Daten werden aus dem Speicher entfernt. 🎜🎜Nach der Garbage Collection: 🎜🎜🎜🎜🎜Nicht erreichbare Datenblöcke 🎜🎜Es ist möglich, dass auf das gesamte verbundene Objekt nicht mehr zugegriffen werden kann und es aus dem Speicher gelöscht wird. 🎜🎜Das Quellobjekt ist das gleiche wie oben. Dann:🎜rrreee🎜Das Bild in der Erinnerung wird:🎜Dieses Beispiel verdeutlicht, wie wichtig das Konzept der Barrierefreiheit ist.
Offensichtlich sind John und Ann immer noch miteinander verbunden, beide haben eingehende Referenzen. Aber das reicht nicht aus.
Die Verknüpfung des Objekts „Familie“ mit der Wurzel wurde aufgehoben, es gibt keine Verweise mehr darauf, sodass der gesamte Block darunter nicht mehr erreichbar ist und gelöscht wird.
Der grundlegende Garbage-Collection-Algorithmus heißt „Mark-Sweep“ und führt regelmäßig die folgenden „Garbage-Collection“-Schritte aus:
Der Garbage Collector erhält die Wurzeln und „Marks“ (merkt sich ) ihnen .
Dann greift es auf alle Referenzen zu und „taggt“ sie.
Anschließend greift es auf die markierten Objekte zu und markiert deren Referenzen. Alle Objekte, auf die zugegriffen wird, werden gespeichert, sodass in Zukunft nicht zweimal auf dasselbe Objekt zugegriffen wird.
Und so weiter, bis es nicht besuchte Referenzen gibt (zugänglich über Root).
Alle Objekte außer den markierten werden gelöscht.
Die Objektstruktur ist beispielsweise wie folgt:
Wir können deutlich erkennen, dass sich rechts ein „unerreichbarer Block“ befindet. Sehen wir uns nun an, wie der Garbage Collector „Mark and Sweep“ damit umgeht. Der erste Schritt besteht darin, die Wurzeln zu markieren Gilt als unzugänglich und wird gelöscht:
So funktioniert die Speicherbereinigung. Die JavaScript-Engine wendet viele Optimierungen an, um die Ausführung zu beschleunigen, ohne die Ausführung zu beeinträchtigen.
Einige Optimierungen:
Generationsrecycling
– Objekte werden in zwei Gruppen unterteilt: „neue Objekte“ und „alte Objekte“. Viele Objekte tauchen auf, erledigen ihre Arbeit und sind schnell fertig, sie werden schnell aufgeräumt. Wer lange genug lebt, wird „alt“ und wird selten untersucht.
Inkrementelles Recycling – Wenn es viele Objekte gibt und wir versuchen, den gesamten Objektsatz auf einmal zu durchlaufen und zu markieren, kann dies einige Zeit dauern und zu Verzögerungen bei der Ausführung führen. Daher versucht die Engine, die Garbage Collection in mehrere Teile aufzuteilen. Anschließend wird jeder Teil einzeln ausgeführt. Dies erfordert zusätzliche Markierungen, um Änderungen zu verfolgen, sodass es eher zu vielen kleinen Verzögerungen als zu großen Verzögerungen kommt.
Leerlaufzeiterfassung
– Der Garbage Collector läuft nur, wenn die CPU im Leerlauf ist, um mögliche Auswirkungen auf die Ausführung zu reduzieren.1) Fragen Sie, was Müll ist
Im Allgemeinen sind Objekte, auf die nicht verwiesen wird, Müll und müssen gelöscht werden. Es gibt eine Ausnahme, wenn mehrere Objektreferenzen einen Ring bilden und darauf verweisen Aber auch diese Objekte sind Müll und müssen gelöscht werden.Einer Algorithmus ist der Mark-Clear-Algorithmus. Ich möchte auch über verschiedene Algorithmen sprechen.
Eine ausführlichere ErklärungWeitere Kenntnisse zum Thema Programmierung finden Sie unter: Einführung in die Programmierung
! !Das obige ist der detaillierte Inhalt vonVerstehen Sie den Garbage-Collection-Mechanismus in JavaScript. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!