Maison  >  Article  >  interface Web  >  Quelle est l'utilisation de la mémoire en js ? Comprendre le rôle de la mémoire js

Quelle est l'utilisation de la mémoire en js ? Comprendre le rôle de la mémoire js

不言
不言original
2018-08-16 15:09:251513parcourir

Le contenu de cet article porte sur quelle est l'utilisation de la mémoire en js ? Il a une certaine valeur de référence pour comprendre le rôle de la mémoire js. Les amis dans le besoin peuvent s'y référer. J'espère qu'il vous sera utile.

Dans le processus de développement JS, comprendre le mécanisme de mémoire JS aide les développeurs à comprendre clairement ce qui s'est passé lors de l'exécution du code qu'ils ont écrit et peut également améliorer la qualité du code du projet.

À quoi ressemble la mémoire JS ?

Le stockage des variables dans JS est divisé en valeurs d'origine et valeurs de référence :

  • Valeur d'origine : type de données d'origine : undefined , null, number, string, boolean et la valeur de référence symbol nouvellement ajoutée.

  •  : object, array, function et d'autres types de valeurs sont des valeurs de référence.

La mémoire dans JS est également divisée en mémoire de pile et mémoire de tas. Pour des informations détaillées sur le tas et la pile, veuillez voir ici. par exemple :

const str = '我是说明内存的文档'; // 这里 str 以及 '我的说明内存的文档' 都存储在栈内存当中
const obj = { a: 1 }; // 这里 obj(指向存储在堆中的数据的指针) 是存储在栈内存 而 { a: 1 } 则存储在堆当中
Quel est le cycle de déclaration des objets de stockage en mémoire ?

Introduction dans MDN :

  1. Quand l'objet sera alloué mémoire pour celui-ci en cas de besoin.

  2. Utiliser la mémoire allouée (opérations de lecture et d'écriture)

  3. Lorsque l'objet n'est plus nécessaire

1 est le même dans toutes les langues, 2 n'est pas si évident en JS 3

Regardez ce qui se passe dans la mémoire ?

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了. (这里它们是指向了堆内存中的不同数据的不同的指针)
Alors regardez cette question :

let a = { n: 1 };
let b = a;
a.x = a = { n: 2 };
Regardez l'explication détaillée, il est toujours très utile de comprendre les points de connaissances de base. Par exemple : L'ordre des opérations d'affectation dans js est toujours de. de droite à gauche, mais

est l'opérateur avec la priorité la plus élevée .

Les changements dans le transfert de valeur de fonction du point de vue de la mémoire

À propos du passage Explication de la valeur/adresse Utilisez les types primitifs et. types de référence à distinguer. Le type primitif transmet la valeur et le type référence transmet l'adresse.

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

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

, vous pouvez voir que l'entrant#1 est la valeur de fn, et un nouvel espace est alloué dans la mémoire de la pile pour enregistrer les paramètres de la fonction et leurs valeurs (cette partie de la mémoire est automatiquement libérée après l'exécution de la fonction, _mécanisme de collecte des ordures_ Par conséquent, la sortie est sortie dans La valeur est str. Lors de l'appel de la fonction #2, une valeur est transmise au paramètre 我是修改后的字符串 (données nouvellement allouées dans la mémoire de la pile), et fn est un type primitif de sortie et d'initialisation. arg Les définitions restent cohérentes. str#3

Les deux fonctions de l'exemple ci-dessus sont passées par adresse. Les paramètres initialement passés
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}
sont tous des références (pointeurs pointant vers les mêmes données dans la mémoire du tas). . Réaffectez un nouvel objet (type référence) à la variable

dans arg. Le fn dans arg est toujours une référence (un pointeur vers les données dans la mémoire du tas), donc la modification est dans <.> Réussi.fn1argMécanisme de récupération de placefn1

JS dispose d'un mécanisme de récupération de place, ce qui apporte une grande commodité aux développeurs. Au moins, ils n'ont pas à trop penser à la libération de mémoire (certaines parties). doivent encore être pris en compte) ).

Les variables de la fonction n'existent que pendant l'exécution de la fonction. Lors de l'exécution de la fonction, les variables à l'intérieur de la fonction alloueront une certaine. de l'espace dans la mémoire. Lorsque la fonction est exécutée, après cela, ces variables sont automatiquement libérées de la mémoire pour laisser de l'espace pour d'autres utilisations
  • Lorsqu'une variable dans la mémoire n'est plus. référencé, JS nettoiera cette partie de l'allocation de mémoire, par exemple :
  • Optimisation de la mémoire
let obj = { a: 1 }; // 内存中存在{a: 1}对象, 以及obj这个引用地址
obj = { a: 2 }; // 垃圾回收机制自动清理{a: 1}, 并为新的有用的{a: 2}分配空间
En ce qui concerne les variables globales, JS ne peut pas déterminer si. il sera utilisé plus tard, il a donc été utilisé depuis qu'il a été déclaré. Existe en mémoire jusqu'à sa libération manuelle ou la fermeture de la page/du navigateur, ce qui entraîne une consommation de mémoire inutile.

Utiliser les fonctions d'exécution immédiate


Accès manuel aux références de variables

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

En JS, les fermetures sont les plus susceptibles de provoquer des problèmes de mémoire. Nous pouvons utiliser des fonctions de rappel au lieu de fermetures pour accéder aux variables internes. L'avantage de l'utilisation des rappels est que (les variables internes accessibles sont des valeurs de type primitif, car les valeurs sont transmises lorsque la fonction passe des paramètres), les variables seront automatiquement libérées. après l'exécution, et ne seront pas conservés comme les fermetures. Les variables internes existent en mémoire (mais s'il s'agit d'un type référence, alors l'objet référencé est toujours en mémoire

let obj = { a: 1, b: 2, c: 3 };
obj = null;
Dans l'exemple ci-dessus, bien que). la fonction

a été exécutée, mais pour la fonction La référence à la variable

est toujours là, donc le mécanisme de garbage collection ne recyclera pas le
function fn() {
    var val = '你好';
    return function() {
            return val
        };
};
var getVal = fn();
var v = getVal(); // 你好
dans la fonction. est déclaré en même temps en utilisant le rappel

fnvalval , ne veut pas dire que cela est nécessairement mieux que les fermetures. Les fermetures ont aussi leurs avantages, mais il suffit de faire la distinction entre leur utilisation et leur utilisation. le moment le plus approprié.

Recommandations associées :

Explication de l'exemple de gestion de la mémoire JS
function fn1(cb) {
    var val = '你好';
    return cb(val);
};
function fn2(arg) {
    return arg;
};
var v = fn1(fn2);

Analyse de la méthode de libération de mémoire en JS. bibliothèque de classes Bindows1.3_javascript skills


Explication de l'exemple de gestion de la mémoire JS

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn