Werden primitive Typen in ---- Grundtypen von Nicht-Grundtypen Angesichts dieser Frage glaube ich, dass jeder das Gefühl hat, dass sie so grundlegend ist, dass sie noch grundlegender nicht sein kann. Durchsuchen Sie einfach Baidu und Sie werden viele Leute sehen, die sagen: Basistypen werden im Stapel gespeichert und Referenztypen im Heap. Ist es wirklich so einfach? 1. Der Elefant, der nicht in den Kühlschrank passtSchauen wir uns diesen Code an: Hier deklarieren wir eine 67-MiB-Zeichenfolge, die schwer zu erklären wäre, wenn die Zeichenfolge tatsächlich auf dem Stapel vorhanden wäre. Schließlich beträgt die Standard-Stapelgröße von v8 984 KiB. Es ist definitiv nicht mehr zu retten. Hinweis: V8 hat in verschiedenen Betriebssystemen und zu verschiedenen Zeiten unterschiedliche Beschränkungen der Zeichenfolgengröße. Der ungefähre Bereich beträgt 256 MiB ~ 1 GiB Knoten --v8-Optionen | grep -B0 -A1 Stapelgröße Beginnen Sie an diesem Punkt, sich zu wundern? Ist es möglich, dass die Antwort von Baidu falsch ist und ich bei Google suchen muss? Mal sehen, was los ist. 2. Schattenklon-Zeichenfolgeconst BasicVarGen = Funktion () { dies.s1 = "IAmString" dies.s2 = "IAmString" } lass a = neues BasicVarGen() lass b = neues BasicVarGen() Hier deklarieren wir zwei identische Objekte, die jeweils zwei identische Zeichenfolgen enthalten. Durch die Entwicklertools können wir sehen, dass, obwohl wir vier Zeichenfolgen deklariert haben, ihr Speicher auf dieselbe Adresse verweist. Hinweis: Was bedeutet das? Es zeigt sich, dass die vier Zeichenfolgen Referenzadressen enthalten. Der Elefant im obigen Artikel, der nicht in den Kühlschrank passt, ist also leicht zu erklären. Der String wird nicht im Stack gespeichert, sondern an einer anderen Stelle und die Adresse dieser Stelle wird dann im Stack gespeichert. Ändern wir also den Inhalt einer der Zeichenfolgen. const BasicVarGen = Funktion () { dies.s0 = "IAmString" dies.s1 = "IAmString" } lass a = neues BasicVarGen() lass b = neues BasicVarGen() Debugger a.s0 = 'andere Zeichenfolge' a.s2 = "IAmString" Speicherabbild vor dem Speicherabbild nach dem Wir können sehen, dass der anfängliche Inhalt von a.s0 „ Die neu hinzugefügte Variable a.s2 hat den Inhalt „ Wenn wir eine Zeichenfolge deklarieren:
Also lasst uns das klären. Wenn wir einen String erstellen, durchsucht V8 zuerst den Speicher (Hash-Tabelle), um zu sehen, ob es einen identischen String gibt, der bereits erstellt wurde. Wenn es ihn gibt, wird er direkt wiederverwendet. Wenn es nicht existiert, wird ein neuer Speicherplatz zum Speichern der Zeichenfolge geöffnet und anschließend die Adresse der Variablen zugewiesen. Aus diesem Grund können wir Zeichenfolgen nicht direkt mithilfe von Indizes ändern: Zeichenfolgen in V8 sind unveränderlich. Nehmen Sie als Beispiel eine grundlegende Typkopie von js, um die Implementierungslogik von v8 und die herkömmliche Logik zu erklären, die jeder versteht (Yawen). Beispiel: var a = "刘潇洒"; // Nachdem V8 den String gelesen hat, sucht es in der String-Tabelle nach, ob er existiert. Wenn er nicht existiert, fügt es '刘潇洒' in die Hash-Tabelle ein und speichert die Referenz von '刘潇洒' in einem var b = a; // Kopiere direkt die Referenz von '刘潇洒' b = "谭雅文"; // Suche nach keinem Eintrag in der Zeichenfolgentabelle Fragen: const BasicVarGen = Funktion () { dies.s0 = "IAmString" dies.s1 = "IAmString" } lass a = neues BasicVarGen() lass b = neues BasicVarGen() Debugger a.s0 = 'andere Zeichenfolge' a.s2 = "IAmString" a.s3 = a.s2+a.s0; // Frage: Welche Operationen werden bei der Zeichenkettenverkettung ausgeführt? a.s4 = a.s2+as Gilt für zwei gleichzeitig verknüpfte Zeichenfolgen mit demselben Inhalt. Wie Sie sehen, ist der Inhalt derselbe. Die Adressen sind jedoch nicht dieselben. Darüber hinaus hat sich auch die Kartenbeschreibung vor der Adresse geändert.
Wenn dies für Zeichenfolgen gilt, gilt es dann auch für andere primitive Typen? 3. Der „seltsame Ball“, den ich persönlich sehe Nachdem wir über Zeichenfolgen gesprochen haben, schauen wir uns einen anderen typischen „Basistyp“ in V8 an: Erweitert vom Machen wir noch ein kleines Experiment: Wir können die in der Abbildung oben aufgeführten Grundtypen sehen und die Adressen sind dieselben. Auch bei der Wertezuweisung werden diese an Ort und Stelle wiederverwendet. (Und die Adressen dieser von Schauen wir uns zur Überprüfung den Quellcode an: Generieren Sie verschiedene Wenn einer Variablen Wo der Offset definiert ist 4. Verwirrende ZahlenDer Grund, warum diese Zahl als verwirrend bezeichnet wird, liegt darin, dass der Mechanismus der Speicherzuweisung bei Zuweisung und Änderung noch nicht geklärt ist. (Sein Gedächtnis ist dynamisch) Zahlen werden in V8 in Das niedrigste Bit dient zur Anzeige, ob es sich um einen Zeiger handelt. Wenn das niedrigste Bit 1 ist, handelt es sich um einen Zeiger. Konstante o = { x: 42, // Smi y: 4.2, // HeapNummer }; Die 42 in ox werden als Smi behandelt und direkt im Objekt selbst gespeichert, während die 4,2 in oy in einem zusätzlichen Speicherobjekt gespeichert werden müssen und der Objektzeiger von oy auf das Speicherobjekt zeigt. Wenn es sich um ein 32-Bit-Betriebssystem handelt, ist es verständlich, 32 Bit zur Darstellung von SMI zu verwenden. Warum liegt der SMI-Bereich jedoch bei einem 64-Bit-Betriebssystem auch zwischen -2³¹ und 2³¹-1 (2³¹≈2*10⁹)? Konstantes Zykluslimit = 50000 Konsole.Zeit('Heapnummer') const foo = { x: 1.1 }; für (sei i = 0; i < Zyklusgrenze; ++i) { // Erstellt eine zusätzliche HeapNumber-Instanz foo.x += 1; } console.timeEnd('heapNumber') // langsam Konsole.Zeit('smi') const bar = { x: 1.0 }; für (sei i = 0; i < Zyklusgrenze; ++i) { bar.x += 1; } console.timeEnd('smi') // schnell Fragen: const BasicVarGen = Funktion () { dies.smi1 = 1 dies.smi2 = 2 diese.Heapnummer1 = 1,1 diese.Heapnummer2 = 2,1 } let foo = neues BasicVarGen() let bar = new BasicVarGen() Debugger baz.obj1.heapNumber1++ Bei den Zahlen wird der Wert einer einzelnen Zahl nicht verändert, die Adressen anderer Zahlen werden jedoch geändert. 5. Zusammenfassung: Wo gibt es Basistypen?String: Er existiert im Heap und ist eine Referenzadresse im Stack. Wenn derselbe String existiert, ist die Referenzadresse dieselbe. Zahlen: Kleine Ganzzahlen werden auf dem Stapel gespeichert, andere Typen auf dem Heap. Andere Typen: Beim Initialisieren der Engine wird eine eindeutige Adresse zugewiesen und die Variablen im Stapel speichern eindeutige Referenzen. Hier kann nur grob erklärt werden, wo es die Grundtypen gibt. Damit ist dieser Artikel zu detaillierten Speicherprinzipien und der Frage, ob Variablen in JS im Heap oder im Stack gespeichert werden, abgeschlossen. Weitere Informationen dazu, ob Variablen in JS im Heap oder im Stack gespeichert werden, 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:
|
<<: So führen Sie Linux-Befehle im Hintergrund aus
>>: Allgemeine Lösungen für das Ablaufen der Lese-/Schreibtrennung in MySQL
Nachteile von Tabellen 1. Tabellen nehmen mehr Byt...
1. Einleitung Nach dem Start von MySQL wird Buffe...
Vorwort In der Praxis kann es zu folgendem Proble...
Dieser Artikel stellt hauptsächlich die dynamisch...
1. Heute Nachmittag musste ich aufgrund der Anfor...
Implementierung des Zeitvergleichs in MySql unix_...
Einzigartige „Über“-Seiten Eine gute Möglichkeit, ...
Angesichts der Tatsache, dass mittlerweile viele M...
Bei der Installation von Nginx, MySQL, Tomcat und...
Da dies mein erster Beitrag ist, weisen Sie mich ...
In diesem Artikel wird der spezifische Code von J...
DML-Operationen beziehen sich auf Operationen an ...
Dieser Artikel stammt vom Apache Spark Meetup, da...
HTML-Absatz Absätze werden durch das Tag <p>...