Heim  >  Artikel  >  Web-Frontend  >  Wozu dient Speicher in js? Verstehen Sie die Rolle des js-Speichers

Wozu dient Speicher in js? Verstehen Sie die Rolle des js-Speichers

不言
不言Original
2018-08-16 15:09:251513Durchsuche

Der Inhalt dieses Artikels befasst sich mit der Verwendung von Speicher in js. Es hat einen gewissen Referenzwert, um die Rolle des js-Gedächtnisses zu verstehen. Freunde in Not können sich darauf beziehen.

Im Prozess der JS-Entwicklung hilft das Verständnis des JS-Speichermechanismus den Entwicklern, klar zu verstehen, was während der Ausführung des von ihnen geschriebenen Codes passiert ist, und kann auch die Codequalität des Projekts verbessern.

Wie sieht der JS-Speicher aus?

Variablenspeicher in JS ist in Originalwerte und Referenzwerte unterteilt:

  • Originalwert: Originaldatentyp: undefined , null, number, string, boolean und der neu hinzugefügte symbol.

  • Referenzwert: object, array, function und andere Arten von Werten sind Referenzwerte.

Der Speicher ist in JS auch in Stapelspeicher und Heapspeicher unterteilt. Weitere Informationen zu Heap und Stack finden Sie hier.
zB:

const str = '我是说明内存的文档'; // 这里 str 以及 '我的说明内存的文档' 都存储在栈内存当中
const obj = { a: 1 }; // 这里 obj(指向存储在堆中的数据的指针) 是存储在栈内存 而 { a: 1 } 则存储在堆当中

Wie ist der Lebenszyklus von Speicherobjekten im Speicher?

Einführung in MDN:

  1. Wann wird das Objekt benötigt

  2. Verwenden Sie den zugewiesenen Speicher (Lese- und Schreibvorgänge)

  3. Wenn das Objekt nicht mehr benötigt wird, geben Sie den Speicher frei, in dem dieses Objekt gespeichert ist

1 2Es ist in allen Sprachen das Gleiche, 3In JS ist es nicht so offensichtlich

Sehen Sie, was in der Erinnerung passiert?

let str1 = 1; // 为str1分配栈内存 str1: 1
let str2 = str1; // 原始类型直接访问值, 即为str2新分配栈内存: str2: 1

str2 = 2; // 栈内存: str2: 2. str2的值为2, 而str1的值仍然是1

/************************ 我是分割线: 上面为原始类型 下面为复杂类型 *******************************/

let obj1 = { a: 1 }; // 为obj1分为栈内存访问地址的指针: obj1. 堆内存中存储对象值: { a: 1 }
let obj2 = obj1; // 为obj2分配栈内存访问地址的指针: obj2. 引用了堆内存中的值{ a: 1 }

obj2.a = 2; // 通过obj1修改堆内存的数据, 由于obj2与obj2都是指向堆内存中的同一个数据的指针(也叫引用). 所以堆内存中的值{a: 1}修改为{a: 2} 即 obj1.a 为 2; obj2.a 也为 2; (这里它们是指向了堆内存中的同一个数据的不同指针)

obj2 = { a: 3 }; // 因为改的是整个对象, 这里会在堆内存中创建一个新的对象值: {a:3}, 而obj2引用的是这个新对象, 所以obj1.a 依旧为 2; 而obj2.a 则为 3了. (这里它们是指向了堆内存中的不同数据的不同的指针)

Dann schauen Sie sich diese Frage an:

let a = { n: 1 };
let b = a;
a.x = a = { n: 2 };

Sehen Sie sich die detaillierte Erklärung an, sie ist immer noch sehr hilfreich, um die grundlegenden Wissenspunkte zu verstehen. Zum Beispiel: Die Reihenfolge der Zuweisungsoperationen in js Es ist immer von rechts nach links, aber . ist der Operator mit der höchsten Priorität

Die Änderungen bei der Funktionswertübertragung aus Speichersicht

Erklärung zur Wert-/Adressübertragung unterscheiden. Der primitive Typ übergibt den Wert und der Referenztyp übergibt die Adresse

let str = '我是初始字符串';
let fn = (arg) => {
    console.log(arg); // #1 我是初始字符串

    arg = '我是修改后的字符串';
    console.log(arg); // #2 我是修改后的字符串
    console.log(str); // #3 我是初始字符串
};
fn(str);

Im obigen Beispiel #1 können Sie sehen, dass der übergebene fn die Adresse von str ist , wird im Stapelspeicher neuer Speicherplatz zugewiesen, um die Funktionsparameter und ihre Werte zu speichern (dieser Teil des Speichers wird automatisch freigegeben, nachdem die Funktion ausgeführt wurde, _Garbage-Collection-Mechanismus_, sodass der bei #2 ausgegebene Wert 我是修改后的字符串 ist). . Beim Aufruf der Funktion fn wird ein Wert (neu zugewiesene Daten im Stapelspeicher) an den Parameter arg übergeben, und str ist ein primitiver Typ. Die Ausgabe bei #3 stimmt mit der Initialisierungsdefinition überein .

let obj = { a: 1 };
let fn = (arg) => {
    arg = { a: 2 };
};

fn(obj);
// 这个时候obj还是{a: 1}

let fn1 = (arg) => {
    arg.a = 2;
};
fn1(obj);
// 这个时候obj则为{a: 2}

Beide Funktionen im obigen Beispiel werden per Adresse übergeben. Die anfänglich übergebenen Parameter arg sind alle Referenzen (Zeiger, die auf dieselben Daten im Heap-Speicher zeigen), die in Variablen fn >Weisen Sie ein neues Objekt zu (Referenztyp). Das arg in fn1 ist immer noch eine Referenz (ein Zeiger auf die Daten im Heap-Speicher), sodass die Änderung in arg erfolgreich ist fn1 ist ein Garbage-Recycling-Mechanismus

JS verfügt über einen Garbage-Collection-Mechanismus, der Entwicklern großen Komfort bietet. Zumindest müssen sie sich nicht zu viele Gedanken über die Speicherfreigabe machen (einige davon müssen noch berücksichtigt werden). ).

    Die Variablen der Funktion existieren nur während der Ausführung der Funktion. Während der Ausführung der Funktion belegen die Variablen innerhalb der Funktion einen bestimmten Platz im Speicher Wenn die Funktion ausgeführt wird, werden diese Variablen automatisch aus dem Speicher freigegeben, um Platz für andere Verwendungen zu schaffen.
  • Wenn eine Variable im Speicher nicht mehr referenziert wird, wird JS bereinigt die Zuteilung dieses Teils des Speichers, z. B.:
  • let obj = { a: 1 }; // 内存中存在{a: 1}对象, 以及obj这个引用地址
    obj = { a: 2 }; // 垃圾回收机制自动清理{a: 1}, 并为新的有用的{a: 2}分配空间
  • Speicheroptimierung

Was globale Variablen betrifft, kann JS nicht bestimmen, ob es später verwendet wird, Damit es vom Moment der Deklaration bis zur manuellen Freigabe oder dem Schließen der Seite/des Browsers immer im Speicher vorhanden ist, führt dies zu unnötigem Speicherverbrauch.

Verwenden Sie die Sofortige Ausführungsfunktion

(() => {
    // do something...
})();

Berühren Sie manuell die Referenz der Variablen

let obj = { a: 1, b: 2, c: 3 };
obj = null;
In JS verursachen Schließungen am wahrscheinlichsten Speicherprobleme. Wir können Rückrufe verwenden Funktionen anstelle von Abschlüssen für den Zugriff auf interne Variablen. Der Vorteil der Verwendung von Rückrufen besteht darin, dass (die internen Variablen, auf die zugegriffen wird, primitive Werttypen sind, da der Wert übergeben wird, wenn die Funktion Parameter übergibt), die Variablen nach der Ausführung automatisch freigegeben werden und die internen Variablen sind nicht immer wie ein Abschluss im Speicher vorhanden (wenn es sich jedoch um einen Referenztyp handelt, befindet sich das referenzierte Objekt immer noch im Speicher

function fn() {
    var val = '你好';
    return function() {
            return val
        };
};
var getVal = fn();
var v = getVal(); // 你好

Im obigen Beispiel ist die Funktion

Wurde ausgeführt, ist der Verweis auf die Variable

in der Funktion noch vorhanden, sodass der Garbage-Collection-Mechanismus die Funktion nicht entfernt. fn Recycling in valval

verwendet Rückruf

function fn1(cb) {
    var val = '你好';
    return cb(val);
};
function fn2(arg) {
    return arg;
};
var v = fn1(fn2);
Dies bedeutet nicht unbedingt, dass dies besser ist als die Schließung, aber wir müssen zwischen der Verwendung zum am besten geeigneten Zeitpunkt unterscheiden Verwandte Empfehlungen:

Erläuterung von JS-Speicherverwaltungsbeispielen

JS-Analyse der Speicherfreigabemethode in der Klassenbibliothek Bindows1.3_Javascript-Kenntnisse

Erläuterung von Beispielen für die JS-Speicherverwaltung

Das obige ist der detaillierte Inhalt vonWozu dient Speicher in js? Verstehen Sie die Rolle des js-Speichers. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn