VorwortF: Was ist ein Speicherleck? Der angeforderte Speicher wurde buchstäblich nicht rechtzeitig wiederhergestellt und ist verloren gegangen. F: Warum tritt ein Speicherverlust auf? Obwohl auf der Vorderseite ein Speicherbereinigungsmechanismus vorhanden ist, tritt ein Speicherverlust auf, wenn ein ungenutzter Speicherbereich vom Speicherbereinigungsmechanismus nicht als Müll betrachtet werden kann. Der Garbage Collection-Mechanismus verwendet normalerweise eine Flag-Clearing-Strategie. Einfach ausgedrückt bestimmt er, ob es sich um Müll handelt, indem er sich darauf bezieht, ob es vom Stammknoten aus erreichbar ist. Das Obige ist die Hauptursache für Speicherlecks. Die direkte Ursache ist, dass ein Speicherleck auftritt, wenn zwei Dinge mit unterschiedlichen Lebenszyklen miteinander kommunizieren, eines davon abläuft und recycelt werden sollte, aber immer noch von der anderen Partei gehalten wird. Lassen Sie uns also darüber sprechen, welche Szenarien zu Speicherlecks führen Welche Situationen können Speicherlecks verursachen? 1. Zufällige globale VariablenDer Lebenszyklus globaler Variablen ist am längsten. Sie bleiben bestehen, bis die Seite geschlossen wird, sodass der Speicher globaler Variablen nie wiederverwendet wird. Speicherlecks treten auf, wenn globale Variablen falsch verwendet werden, nicht rechtzeitig wiederverwendet werden (manuell auf Null gesetzt werden) oder aufgrund von Rechtschreibfehlern in globale Variablen eingebunden werden. 2. Timer vergessenDer Lebenszyklus von setTimeout und setInterval wird von einem dedizierten Thread des Browsers verwaltet. Wenn also auf einer Seite ein Timer verwendet wird, ist der Timer weiterhin aktiv, sofern er beim Zerstören der Seite nicht manuell freigegeben und bereinigt wird. Mit anderen Worten, der Lebenszyklus des Timers ist nicht an die Seite gebunden. Wenn also eine Rückruffunktion über den Timer im JS der aktuellen Seite registriert wird und die Rückruffunktion eine Variable oder einige DOM-Elemente der aktuellen Seite enthält, führt dies dazu, dass die Seite zerstört wird. Der Teil der Seite, auf den der Timer verweist, kann nicht normal recycelt werden, was zu Speicherlecks führt. Wenn Sie zu diesem Zeitpunkt dieselbe Seite erneut öffnen, befinden sich tatsächlich zwei Kopien der Seitendaten im Speicher. Wenn Sie sie viele Male schließen und öffnen, wird der Speicherverlust immer schwerwiegender. Dieses Szenario kann leicht auftreten, da Benutzer von Timern leicht vergessen können, sie zu löschen. 3. Unsachgemäßer Einsatz von VerschlüssenDie Funktion selbst enthält einen Verweis auf die lexikalische Umgebung, in der sie definiert ist. Normalerweise wird jedoch nach der Verwendung der Funktion der von der Funktion angeforderte Speicher zurückgefordert. Wenn jedoch eine Funktion innerhalb einer Funktion zurückgegeben wird, enthält die zurückgegebene Funktion die lexikalische Umgebung der externen Funktion und die zurückgegebene Funktion wird von anderen Lebenszyklusobjekten gehalten, was dazu führt, dass die externe Funktion ausgeführt wird, der Speicher jedoch nicht zurückgefordert werden kann. Daher sollte der Lebenszyklus der zurückgegebenen Funktion nicht zu lang sein, damit der Abschluss rechtzeitig recycelt werden kann. Normalerweise sind Closures keine Speicherlecks, da das Halten der lexikalischen Umgebung der externen Funktion eine Funktion von Closures ist, die die Wiederverwendung dieses Speichers verhindern soll. Dies kann in Zukunft erforderlich sein, verursacht jedoch zweifellos Speicherverbrauch. Daher ist eine übermäßige Nutzung nicht ratsam. 4. Fehlende DOM-ElementeDer Lebenszyklus eines DOM-Elements hängt normalerweise davon ab, ob es im DOM-Baum montiert ist. Wenn es aus dem DOM-Baum entfernt wird, kann es zerstört und wiederverwendet werden. Wenn jedoch auch in js auf ein DOM-Element verwiesen wird, wird sein Lebenszyklus sowohl von js als auch davon bestimmt, ob es sich im DOM-Baum befindet. Denken Sie daran, dass beim Entfernen beide Stellen bereinigt werden müssen, um es normal wiederzuverwenden. 5. Netzwerk-RückrufIn einigen Szenarien wird eine Netzwerkanforderung auf einer Seite initiiert und ein Rückruf registriert. Die Rückruffunktion enthält einen Teil des Seiteninhalts. Wenn die Seite dann zerstört wird, sollte der Netzwerkrückruf nicht registriert werden. Andernfalls kann ein Teil des Seiteninhalts nicht wiederverwendet werden, da das Netzwerk einen Teil des Seiteninhalts enthält. So überwachen Sie SpeicherlecksSpeicherlecks können in zwei Kategorien unterteilt werden. Die eine ist schwerwiegender und der verlorene Speicher kann nicht wiederhergestellt werden. Die andere ist weniger schwerwiegend und wird durch Speicherlecks verursacht, die nicht rechtzeitig behoben werden. Sie können nach einer gewissen Zeit immer noch behoben werden. Unabhängig davon, welches Sie verwenden, sollten Sie anhand des vom Entwicklertool erfassten Speicherdiagramms sehen, dass die Speichernutzung im Laufe der Zeit weiterhin linear abnimmt. Dies liegt daran, dass ständig eine GC (Garbage Collection) stattfindet. Beim ersten Typ, der schwerwiegender ist, werden Sie feststellen, dass die Gesamtmenge des verwendeten Speichers auch dann noch zunimmt, wenn im Speicherdiagramm kontinuierlich eine GC auftritt. Darüber hinaus führt unzureichender Speicher zu einer kontinuierlichen GC, und GC blockiert den Hauptthread, was die Seitenleistung beeinträchtigt und zu Staus führt. Daher muss weiterhin auf Speicherlecks geachtet werden. Nehmen wir ein solches Szenario an und verwenden Entwicklertools, um nach Speicherlecks zu suchen: Szenario 1: In einer Funktion wird ein Speicherblock angefordert und die Funktion dann innerhalb kurzer Zeit wiederholt aufgerufen. // Klicken Sie auf die Schaltfläche, um die Funktion einmal auszuführen und einen Speicherbereich anzufordern startBtn.addEventListener("click", function() { var a = neues Array(100000).fill(1); var b = neues Array(20000).fill(1); }); Der Speicher, den eine Seite verwenden kann, ist begrenzt. Wenn der Speicher nicht ausreicht, wird der Speicherbereinigungsmechanismus ausgelöst, um den ungenutzten Speicher wiederzuverwenden. Die in der Funktion verwendeten Variablen sind alle lokale Variablen. Nach Ausführung der Funktion ist dieser Speicher nutzlos und kann wiederverwendet werden. Wenn wir diese Funktion also in kurzer Zeit wiederholt aufrufen, können wir feststellen, dass bei der Ausführung der Funktion festgestellt wird, dass nicht genügend Speicher vorhanden ist. Der Speicherbereinigungsmechanismus arbeitet daran, den von der vorherigen Funktion angeforderten Speicher wiederzuverwenden. Da die vorherige Funktion ausgeführt wurde, ist der Speicher nutzlos und kann wiederverwendet werden. Das Diagramm, das die Speichernutzung zeigt, ist also eine horizontale Linie mit mehreren vertikalen Linien in der Mitte, was tatsächlich bedeutet, dass der Speicher gelöscht, neu zugewiesen, gelöscht und neu zugewiesen wird. Die Position jeder vertikalen Linie ist die Zeit, zu der der Speicherbereinigungsmechanismus funktioniert und die Funktion ausgeführt und neu zugewiesen wird. Szenario 2: In einer Funktion wird ein Speicherblock angefordert. Anschließend wird die Funktion in kurzer Zeit wiederholt aufgerufen, aber ein Teil des jedes Mal angeforderten Speichers wird extern gehalten. // Klicken Sie auf die Schaltfläche, um die Funktion einmal auszuführen und einen Teil des Speichers anzufordern. var arr = []; startBtn.addEventListener("klicken", function() { var a = neues Array(100000).fill(1); var b = neues Array(20000).fill(1); arr.push(b); }); Was ist der Unterschied zum ersten Bild? Es handelt sich nicht mehr um eine horizontale Linie, und die Unterkanten der einzelnen vertikalen Linien in der horizontalen Linie liegen nicht auf derselben Höhe. Dies ist tatsächlich ein Speicherleck. Wir beantragen in der Funktion zwei Array-Speicher, aber eines der Arrays wird extern gehalten. Selbst nach der Ausführung jeder Funktion kann dieser extern gehaltene Teil des Array-Speichers nicht wiederhergestellt werden, sodass jedes Mal nur ein Teil des Speichers wiederhergestellt werden kann. Auf diese Weise kann bei steigender Anzahl von Funktionsaufrufen nicht mehr Speicher wiederhergestellt werden und es treten mehr Speicherlecks auf, wodurch die Speichernutzung weiter zunimmt. Darüber hinaus können Sie auch das Leistungsüberwachungstool verwenden. Suchen Sie in den Entwicklertools nach der Schaltfläche „Mehr“ und öffnen Sie dieses Funktionsfenster. Dies ist ein Tool, mit dem die Nutzung von CPU, Speicher usw. in Echtzeit überwacht werden kann. Es ist intuitiver als das obige Tool, das nur einen Zeitraum erfassen kann: Der leiterartige Anstieg weist auf einen Speicherverlust hin. Bei jedem Funktionsaufruf werden einige Daten extern gespeichert und können nicht wiederverwendet werden. Der gleichmäßige Anstieg weist darauf hin, dass die Daten nach jeder Verwendung normal wiederverwendet werden können. Beachten Sie, dass am Ende des ersten roten Kästchens eine gerade Linie verläuft. Dies liegt daran, dass ich den Code geändert und die Codezeile entfernt habe, die für das Array in der externen Haltefunktion galt. Anschließend habe ich die Seite aktualisiert und manuell auf GC geklickt, um den Effekt auszulösen. Andernfalls kann ein Teil des Speichers nicht wiederhergestellt werden, unabhängig davon, wie Sie auf GC klicken, und dieser Effekt kann nicht erzielt werden. Oben sind einige Tools zur Überwachung von Speicherlecks aufgeführt. Der Schlüssel liegt jedoch im nächsten Schritt. Wie kann nun ein Speicherleck lokalisiert werden? Woher wissen Sie, welcher Teil der Daten nicht wiederhergestellt werden konnte und das Leck verursacht hat? So analysieren Sie Speicherlecks und finden problematischen CodeUm die Ursache von Speicherlecks zu analysieren, müssen Sie weiterhin die Speicherfunktion des Entwicklertools verwenden. Diese Funktion kann Speicher-Snapshots, Speicherzuweisungen innerhalb eines bestimmten Zeitraums und jede Funktion erfassen, die innerhalb eines bestimmten Zeitraums eine Speicherzuweisung auslöst. Mit diesen Tools können wir analysieren, welcher Funktionsvorgang die Speicherzuweisung zu einem bestimmten Zeitpunkt verursacht hat, und analysieren, welche Objekte wiederholt und nicht wiederverwendet werden. Auf diese Weise sind die verdächtigen Funktionen und Objekte bekannt und anschließend wird der Code analysiert, um festzustellen, ob das Objekt in dieser Funktion der Schuldige für den Speicherverlust ist. Betrachten wir zunächst ein einfaches Beispiel und dann ein Beispiel für einen echten Speicherverlust: Szenario 1: In einer Funktion wird ein Speicherblock angefordert. Anschließend wird die Funktion in kurzer Zeit wiederholt aufgerufen, wobei jedoch ein Teil des jedes Mal angeforderten Speichers extern gehalten wird. // Bei jedem Klicken auf eine Schaltfläche kann ein Teil des Speichers nicht wiederhergestellt werden, da er vom externen arr belegt ist. var arr = []; startBtn.addEventListener("klicken", function() { var a = neues Array(100000).fill(1); var b = neues Array(20000).fill(1); arr.push(b); }); Speicherabbild Sie können zwei Snapshots erfassen, zwischen den beiden Snapshots einen Speicherverlustvorgang durchführen und schließlich die Unterschiede zwischen den beiden Snapshots vergleichen, um zu sehen, welche Objekte hinzugefügt und welche wiederverwendet wurden, wie in der obigen Abbildung dargestellt. Sie können auch einen Snapshot zu einem bestimmten Zeitpunkt anzeigen und anhand des Speichernutzungsverhältnisses erkennen, welche Objekte viel Speicher belegen, wie in der folgenden Abbildung dargestellt: Sie können den Garbage Collection-Mechanismus auch verwenden, um zu sehen, welche der vom GC-Stammknoten aus erreichbaren Objekte viel Speicher belegen: Anhand der oben genannten Methoden können Sie überprüfen, welche Objekte derzeit viel Speicher belegen. Im Allgemeinen handelt es sich dabei um die verdächtigen Objekte. Dies ist natürlich nicht unbedingt der Fall. Wenn verdächtige Objekte vorhanden sind, können Sie mehrere Speicherabbilder zum Vergleichen verwenden, zwischendurch manuell eine GC erzwingen und prüfen, ob die wiederhergestellten Objekte wiederhergestellt wurden. Dies ist eine Idee. Erfassen der Speicherzuordnung innerhalb eines bestimmten Zeitraums Mit dieser Methode lässt sich selektiv anzeigen, welche Funktion den jeweiligen Moment der Speicherzuweisung initiiert hat und welches Objekt im Speicher abgelegt ist. Natürlich ist die Speicherzuweisung ein normales Verhalten. Was Sie hier sehen, erfordert auch andere Daten, um zu bestimmen, ob ein Objekt verdächtig ist, wie z. B. das Speichernutzungsverhältnis oder eine Kombination mit Speicher-Snapshots usw. Erfassen Sie die Speichernutzung einer Funktion über einen bestimmten Zeitraum Dabei werden nur sehr wenige Inhalte angezeigt, die relativ einfach gehalten sind und einen klaren Zweck verfolgen, nämlich welche Operationen Speicher beanspruchen und wie viel Speicher in einem bestimmten Zeitraum verbraucht wird. Kurz gesagt, diese Tools können Ihnen keine direkte Antwort geben und Ihnen sagen, dass xxx der Schuldige des Speicherverlusts ist. Wenn dies auf Browserebene festgestellt werden kann, warum wird es dann nicht recycelt und verursacht einen Speicherverlust? Daher können Ihnen diese Tools nur verschiedene Informationen zur Speichernutzung liefern. Sie müssen diese Informationen verwenden und anhand der Logik Ihres eigenen Codes analysieren, welche verdächtigen Objekte die Ursache für Speicherlecks sind. BeispielanalyseHier ist ein Beispiel für einen Speicherverlust, der in vielen Artikeln im Internet auftaucht: var t = null; var replaceThing = Funktion() { var o = t var unbenutzt = function() { wenn (o) { console.log("hallo") } } t = { longStr: neues Array(100000).fill('*'), irgendeineMethode: function() { console.log(1) } } } setzeInterval(Ersatzteil, 1000) Vielleicht haben Sie noch nicht herausgefunden, ob dieser Code einen Speicherverlust verursacht. Keine Sorge. Lassen Sie uns zunächst über den Zweck dieses Codes sprechen. Er deklariert eine globale Variable t und eine replaceThing-Funktion. Der Zweck der Funktion besteht darin, der globalen Variable ein neues Objekt zuzuweisen. Dann gibt es eine interne Variable, um den Wert der globalen Variable t zu speichern, bevor sie ersetzt wird. Schließlich führt der Timer regelmäßig die replaceThing-Funktion aus.
Lassen Sie uns das Tool verwenden, um zu sehen, ob ein Speicherverlust vorliegt: Alle drei Speicherüberwachungsdiagramme zeigen, dass ein Speicherverlust aufgetreten ist: Der Speicher nimmt leiterartig zu, wenn dieselbe Funktion wiederholt ausgeführt wird, und der Speicher nimmt nicht ab, wenn GC manuell angeklickt wird, was darauf hinweist, dass bei jeder Ausführung der Funktion ein Speicherverlust auftritt. Diese Situation, in der selbst eine manuell erzwungene Speicherbereinigung den Speicher nicht reduzieren kann, ist sehr ernst. Wenn sie über einen längeren Zeitraum anhält, wird der verfügbare Speicher erschöpft, was dazu führt, dass die Seite einfriert oder sogar abstürzt.
Nachdem wir nun festgestellt haben, dass ein Speicherverlust vorliegt, besteht der nächste Schritt darin, die Ursache für den Speicherverlust herauszufinden. Zunächst lokalisieren wir den Verdächtigen über das Sampling-Profil in der Funktion „ReplaceThing“. Als nächstes machen wir zwei Speicherauszüge und vergleichen sie, um zu sehen, ob wir Informationen erhalten können: Beim Vergleich der beiden Schnappschüsse können wir feststellen, dass das Array-Objekt während dieses Prozesses zugenommen hat und dass dieses Array-Objekt aus dem „longStr“-Attribut des Objekts stammt, das innerhalb der „replaceThing“-Funktion erstellt wurde. Tatsächlich enthält dieses Bild viele Informationen, insbesondere das verschachtelte Bild unten. Die verschachtelte Beziehung ist umgekehrt. Wenn Sie es rückwärts betrachten, können Sie feststellen, wie das globale Objekt Window Schritt für Schritt auf das Array-Objekt zugreift. Der Garbage Collection-Mechanismus kann nicht recycelt werden, da ein solcher erreichbarer Zugriffspfad vorhanden ist. Tatsächlich können wir es hier analysieren. Um weitere Tools zu verwenden, ändern wir das Bild, um es zu analysieren. Beginnen wir direkt mit dem zweiten Speicherauszug und sehen uns an: Vom ersten bis zum zweiten Snapshot wurde replaceThing 7 Mal ausgeführt und hat genau 7 Objekte erstellt. Es scheint, dass diese Objekte nicht wiederverwendet wurden. Warum wird es also nicht recycelt? Die Funktion „replaceThing“ speichert das vorherige Objekt nur intern. Aber sollten die lokalen Variablen nicht wiederverwendet werden, wenn die Funktion beendet ist? Betrachtet man das Bild weiter, erkennt man, dass sich darunter eine Closure befindet, die viel Speicher beansprucht: Warum können die darin erstellten Objekte nicht bei jedem Aufruf der Funktion „replaceThing“ wiederverwendet werden? Da replaceThing zum ersten Mal erstellt wird, wird dieses Objekt von der globalen Variable t gehalten und kann daher nicht wiederverwendet werden. Bei jedem nachfolgenden Aufruf wird dieses Objekt von der lokalen Variable „o“ innerhalb der vorherigen Funktion „replaceThing“ gehalten und kann nicht wiederhergestellt werden. Die lokale Variable o in dieser Funktion wird von der Methode someMethod des Objekts gehalten, das beim ersten Aufruf von replaceThing erstellt wird. Das von dieser Methode bereitgestellte Objekt wird von der globalen Variable t gehalten und kann daher nicht wiederhergestellt werden. Auf diese Weise werden bei jedem Aufruf einer Funktion die lokalen Variablen beibehalten, die intern beim letzten Aufruf der Funktion erstellt wurden. Dies führt dazu, dass diese lokalen Variablen auch nach Ausführung der Funktion nicht wiederhergestellt werden können. Es ist ein bisschen verwirrend, es verbal auszudrücken, aber hier ist ein Bild (gelöscht, falls es Ihre Rechte verletzt). In Kombination mit der Mark-and-Sweep-Methode (allgemein bekannt als Erreichbarkeitsmethode) des Garbage-Collection-Mechanismus wird es sehr deutlich:
Durch die Verwendung des Speicheranalysetools können folgende Informationen gewonnen werden:
Das Obige ist die Schlussfolgerung, aber wir müssen noch analysieren, warum dies geschieht, nicht wahr? Tatsächlich handelt es sich hierbei um den Wissenspunkt der Schließung: MDN erklärt Closure als die Kombination eines Funktionsblocks und der lexikalischen Umgebung, in der die Funktion definiert ist. Wenn eine Funktion definiert ist, gibt es ein internes Attribut des Bereichs, das die aktuelle lexikalische Umgebung speichert. Sobald eine Funktion von etwas gehalten wird, dessen Lebenszyklus länger ist als die lexikalische Umgebung, in der sie sich befindet, kann die von der Funktion gehaltene lexikalische Umgebung daher nicht wiederverwendet werden. Einfach ausgedrückt: Wenn eine externe Funktion innerhalb einer Funktion definiert ist und die interne Funktion einige Variablen der externen Funktion verwendet, können diese Variablen auch bei Ausführung der externen Funktion nicht wiederverwendet werden, da sie stattdessen in den Eigenschaften der internen Funktion gespeichert sind. Es gibt noch einen weiteren Wissenspunkt: Alle in der externen Funktion definierten Funktionen teilen sich einen Abschluss, d. h. Funktion b verwendet die Variable a der externen Funktion, auch wenn Funktion c sie nicht verwendet, aber Funktion c speichert dennoch die Variable a. Dies wird als gemeinsamer Abschluss bezeichnet. Zurück zu dieser Frage Denn in der Funktion „replaceThing“ wird das intern erstellte Literalobjekt manuell der globalen Variable zugewiesen und dieses Objekt verfügt auch über eine Methode „someMethod“. Aufgrund der Closure-Funktion speichert die Methode „someMethod“ daher die Variable „replaceThing“. Obwohl someMethod keine lokalen Variablen verwendet, gibt es in replaceThing eine unbenutzte Funktion. Diese Funktion verwendet die lokale Variable o. Aufgrund des gemeinsamen Abschlusses speichert someMethod auch o. Und o speichert auch den Wert der globalen Variable t, bevor er ersetzt wird. Daher hält bei jedem Funktionsaufruf jemand die interne Variable o fest, sodass sie nicht wiederverwendet werden kann. Um diesen Speicherverlust zu beheben, müssen Sie den Halter von o abschneiden, damit die lokale Variable o normal wiederverwendet werden kann. Es gibt also zwei Ideen: Entweder lassen Sie someMethod o nicht speichern oder geben Sie o nach der Verwendung frei. Wenn die nicht verwendete Funktion nutzlos ist, können Sie die Funktion direkt entfernen und die Auswirkungen sehen: Der Grund, warum der Speicher hier leiterartig ansteigt, ist, dass der aktuelle Speicher noch ausreichend ist und der Garbage Collection-Mechanismus nicht ausgelöst wurde. Sie können die Garbage Collection manuell auslösen oder sie eine Weile laufen lassen und warten, bis die Garbage Collection funktioniert, um zu prüfen, ob der Speicher auf den Anfangszustand zurückfällt. Dies zeigt an, dass der gesamte Speicher recycelt werden kann. Oder Sie können einen Speicher-Snapshot erstellen, um zu sehen, dass beim Erstellen eines Snapshots die automatische GC-Ausführung erzwungen wird, bevor der Snapshot erstellt wird: Richtig? Auch wenn die Funktion replaceThing regelmäßig aufgerufen wird, speichert die lokale Variable o in der Funktion den Wert der vorherigen globalen Variable t, aber es handelt sich schließlich um eine lokale Variable. Wenn nach Ausführung der Funktion kein externer Verweis darauf vorhanden ist, kann sie wiederverwendet werden, sodass am Ende nur das in der globalen Variable t gespeicherte Objekt im Speicher verbleibt. Wenn die nicht verwendete Funktion nicht entfernt werden kann, können Sie natürlich nur daran denken, die Variable o nach ihrer Verwendung manuell freizugeben: var unbenutzt = function() { wenn (o) { console.log("hallo") o = null; } } Dieser Ansatz behebt jedoch nicht die Grundursache, da dieser Speicherstapel vor der Ausführung der nicht verwendeten Funktion noch vorhanden ist und immer noch verloren geht und nicht wiederhergestellt werden kann. Der Unterschied zum Anfang besteht darin, dass die nicht verwendete Funktion zumindest nach der Ausführung freigegeben werden kann. Tatsächlich sollten wir uns überlegen, ob es hier Probleme mit dem Code gibt, warum lokale Variablen zur Speicherung benötigt werden, warum die nicht verwendete Funktion benötigt wird und was der Zweck dieser Funktion ist. Wenn es nur darum geht, festzustellen, ob die vorherige globale Variable t irgendwann in der Zukunft verfügbar ist, warum dann nicht einfach eine andere globale Variable verwenden, um sie zu speichern? Warum eine lokale Variable wählen? Daher sollten Sie beim Schreiben von Code Szenarien mit Closures besonders beachten. Bei unsachgemäßer Verwendung können schwerwiegende Speicherlecks auftreten. Sie sollten bedenken, dass Closures Funktionen ermöglichen, externe lexikalische Umgebungen zu halten, wodurch einige Variablen in der externen lexikalischen Umgebung nicht wiederverwendet werden können. Außerdem gibt es die Funktion, Closures gemeinsam zu nutzen. Nur wenn Sie diese beiden Punkte verstehen, können Sie richtig überlegen, wie Closures in Anwendungsszenarien implementiert werden, um schwerwiegende Speicherlecks zu vermeiden. ZusammenfassenDamit ist dieser Artikel über Speicherleckszenarien bei JS sowie deren Überwachung und Analyse abgeschlossen. Weitere Informationen zur Überwachung von Speicherleckszenarien bei JS finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, Sie werden 123WORDPRESS.COM auch in Zukunft unterstützen! Das könnte Sie auch interessieren:
|
<<: Grafisches Tutorial zur Installation und Konfiguration der MySQL-Version 8.0.24
>>: CSS implementiert den Texteingabefeldstil von Google Material Design (empfohlen)
Die Konfigurationssyntax von Nginx ist flexibel u...
Liste der HTTP-Rückgabecodes (unten finden Sie ei...
1. Das Startmenü besteht darin, den Cursor in die...
Sie können Docker installieren und einfache Vorgä...
Vorwort: Kürzlich stieß ich in meinem Projekt auf...
ngx_lua_module ist ein Nginx-HTTP-Modul, das den ...
1. Stellen Sie zunächst eine Remoteverbindung zum...
1》Seien Sie gut im Webdesign 2》Wissen, wie man Web...
Ich habe bereits einen Artikel über mobile Anpass...
In diesem Artikel wird der spezifische Code der r...
In diesem Artikelbeispiel wird der spezifische Co...
Überblick Ich habe vor Kurzem begonnen, mir Wisse...
Inhaltsverzeichnis 1. Aggregierte Abfrage 1. COUN...
Anforderung: Bei der Anzeige von Daten in einer L...
Ressourcenzusammenführung und -komprimierung für ...