Table des matières
Cycle de vie du cache (mémoire)
Memory Heap and Stack
Pile : allocation de mémoire statique
Heap : Allocation dynamique de mémoire
Exemples
Références en JavaScript
Exemple
Garbage Collection
Nombre de références
Nombre de cycles
Marquer et balayer
Marques déposées
Utilisation de la mémoire
性能
内存泄漏
被遗忘的计时器和回调
被遗忘的计时器
被遗忘的回调
脱离DOM引用
总结
Maison interface Web js tutoriel Explication détaillée de la gestion de la mémoire en JavaScript

Explication détaillée de la gestion de la mémoire en JavaScript

Jan 06, 2021 am 10:14 AM
javascript 内存管理 前端

Explication détaillée de la gestion de la mémoire en JavaScript

Recommandations associées : "Tutoriel vidéo javascript"

La plupart du temps, nous développons uniquement sans comprendre les connaissances en matière de gestion de la mémoire. Le moteur JS s’en chargera pour nous. Cependant, nous rencontrons parfois des problèmes tels que des fuites de mémoire. Ce n'est qu'en connaissant le fonctionnement de l'allocation de mémoire que nous pouvons résoudre ces problèmes.

Dans cet article, nous présentons principalement les principes de fonctionnement de l'allocation de mémoire et du garbage collection et comment éviter certains problèmes courants de fuites de mémoire.

Cycle de vie du cache (mémoire)

Dans JS, lorsque nous créons une variable, une fonction ou tout autre objet, le moteur JS lui alloue de la mémoire et la libère lorsqu'elle n'est plus nécessaire.

Allocation de mémoire est le processus de réservation d'espace en mémoire, tandis que Libérer de la mémoire libère de l'espace pour le préparer à d'autres fins.

Chaque fois que nous allouons une variable ou créons une fonction, le stockage de cette variable passe par les mêmes étapes :

Explication détaillée de la gestion de la mémoire en JavaScript

Allouer de la mémoire

  • JS gère cela pour nous : il alloue la mémoire dont nous avons besoin pour créer l'objet.

Utiliser la mémoire

  • L'utilisation de la mémoire est quelque chose que nous faisons explicitement dans le code : la lecture et l'écriture de la mémoire sont en fait l'utilisation de variables Read et. écrire.

Libérer la mémoire

  • Cette étape est également gérée par le moteur JS, une fois la mémoire allouée libérée, elle peut être utilisée à de nouvelles fins .

« Objet » dans le contexte de la gestion de la mémoire inclut non seulement les objets JS, mais également les fonctions et les étendues de fonctions.

Memory Heap and Stack

Nous savons désormais que pour tout ce que nous définissons dans JS, le moteur alloue de la mémoire et la libère lorsqu'elle n'est plus nécessaire.

La prochaine question qui me vient à l’esprit est : où ces choses seront-elles stockées ?

Le moteur JS peut stocker des données à deux endroits : tas de mémoire et pile. Le tas et la pile sont deux structures de données utilisées par le moteur à des fins différentes.

Pile : allocation de mémoire statique

Explication détaillée de la gestion de la mémoire en JavaScript

La pile est une structure de données utilisée par JS pour stocker des données statiques. Les données statiques sont des données dont le moteur connaît la taille au moment de la compilation. En JS, cela inclut les valeurs primitives (strings, number, boolean, undefined et null) et les types de référence qui pointent vers des objets et des fonctions.

Puisque le moteur sait que la taille ne changera pas, il allouera une quantité fixe de mémoire pour chaque valeur.

Le processus d'allocation de mémoire immédiatement avant l'exécution est appelé allocation de mémoire statique. Les limites de ces valeurs et de l'ensemble de la pile dépendent du navigateur.

Heap : Allocation dynamique de mémoire

Heap est un autre espace où les données sont stockées, où JS stocke les objets et les fonctions .

Contrairement à la pile, le moteur JS n'alloue pas une quantité fixe de mémoire pour ces objets, mais alloue de l'espace selon les besoins. Cette façon d'allouer de la mémoire est également appelée allocation dynamique de mémoire.

Les caractéristiques de ces deux magasins seront comparées ci-dessous :

堆栈
存放基本类型和引用
大小在编译时已知
分配固定数量的内存
对象和函数
在运行时才知道大小
没怎么限制

Exemples

Prenons quelques exemples pour valoriser l’image.

const person = {
  name: 'John',
  age: 24,
};
Copier après la connexion
Copier après la connexion

JS alloue de la mémoire pour cet objet dans le tas. Les valeurs réelles sont toujours les valeurs d'origine, c'est pourquoi elles sont stockées sur la pile.

const hobbies = ['hiking', 'reading'];
Copier après la connexion

Les tableaux sont aussi des objets, c'est pourquoi ils sont stockés dans le tas.

let name = 'John'; // 为字符串分配内存
const age = 24; // 为字分配内存

name = 'John Doe'; // 为新字符串分配内存
const firstName = name.slice(0,4); // 为新字符串分配内存
Copier après la connexion

La valeur d'origine est immuable, donc JS ne modifie pas la valeur d'origine, mais en crée une nouvelle.

Références en JavaScript

Toutes les variables pointent d'abord vers la pile. S'il s'agit d'une valeur non primitive, 堆栈 contient une référence à l'objet dans .

La mémoire du tas n'est pas triée de manière spécifique, nous devons donc en conserver une référence sur la pile. Nous pouvons considérer 引用 comme des adresses, et les objets dans le tas comme les maisons auxquelles appartiennent ces adresses.

Rappelez-vous que JS stocke les objets et les fonctions sur le tas. Les types primitifs et les références sont stockés sur la pile.

Explication détaillée de la gestion de la mémoire en JavaScript

Sur cette photo, nous pouvons observer comment différentes valeurs sont stockées. Remarquez comment person et newPerson pointent vers le même objet.

Exemple

const person = {
  name: 'John',
  age: 24,
};
Copier après la connexion
Copier après la connexion

Cela créera un nouvel objet dans le tas et une référence à l'objet sur la pile.

Garbage Collection

Maintenant, nous savons comment JS alloue de la mémoire pour divers objets, mais dans le cycle de vie de la mémoire, il y a une dernière étape : Libérer la mémoire.

Tout comme l'allocation de mémoire, le moteur JavaScript gère également cette étape pour nous. Plus précisément, le Garbage Collector en est responsable.

Une fois que le moteur JS reconnaît qu'une variable ou une fonction n'est plus nécessaire, il libère la mémoire qu'elle occupait.

Le principal problème est qu'il est indécis de savoir si de la mémoire est encore nécessaire, ce qui signifie qu'il est impossible d'avoir un algorithme capable de collecter immédiatement toute la mémoire qui n'est plus nécessaire au moment où elle l'est. n'est plus nécessaire.

Certains algorithmes peuvent très bien résoudre ce problème. J'aborderai les méthodes les plus couramment utilisées dans cette section : les algorithmes 引用计数 et 标记清除.

Nombre de références

Lorsqu'une variable est déclarée et qu'une valeur de type référence est attribuée à la variable, le nombre de références à cette valeur est 1. Si la même valeur est attribuée à une autre variable, le nombre de références à la valeur est augmenté de 1. A l'inverse, si la variable contenant une référence à cette valeur obtient une autre valeur, le nombre de références à cette valeur est réduit de 1.

Lorsque le nombre de références à cette valeur devient 0, cela signifie qu'il n'y a plus moyen d'accéder à cette valeur, donc l'espace mémoire qu'elle occupe peut être récupéré. De cette façon, la prochaine fois que le garbage collector s'exécutera, il libérera la mémoire occupée par les valeurs sans références.

Regardons l'exemple ci-dessous.

Explication détaillée de la gestion de la mémoire en JavaScript

Veuillez noter que dans la dernière image, seul hobbies est laissé dans le tas, car la dernière référence est l'objet.

Nombre de cycles

引用计数Le problème avec l'algorithme est qu'il ne prend pas en compte les références circulaires. Cela se produit lorsqu'un ou plusieurs objets se réfèrent les uns aux autres mais qu'ils ne sont plus accessibles via le code.

let son = {
  name: 'John',
};

let dad = {
  name: 'Johnson',
}

son.dad = dad;
dad.son = son;

son = null;
dad = null;
Copier après la connexion

Explication détaillée de la gestion de la mémoire en JavaScript

Puisque les objets parents font référence les uns aux autres, l'algorithme ne libère pas la mémoire allouée et on ne peut plus accéder aux deux objets.

Les définir sur null ne fera pas reconnaître par l'algorithme de comptage de références qu'elles ne sont plus utilisées, car elles ont toutes des références entrantes.

Marquer et balayer

L'algorithme de marquage et de balayage propose des solutions pour les dépendances cycliques. Il détecte s'ils sont accessibles depuis root objets au lieu de simplement calculer la référence à l'objet donné.

Le root du navigateur est un objet window, tandis que le root dans NodeJS est un global.

Explication détaillée de la gestion de la mémoire en JavaScript

L'algorithme marque les objets inaccessibles comme des déchets, puis les analyse (les collecte). L'objet racine ne sera jamais collecté.

De cette façon, les dépendances circulaires ne sont plus un problème. Dans l'exemple précédent, ni l'objet dad ni l'objet son ne sont accessibles depuis la racine. Ils seront donc tous marqués comme déchets et collectés.

Cet algorithme est implémenté dans tous les navigateurs modernes depuis 2012. Seules les performances et la mise en œuvre ont été améliorées, mais l'idée centrale de l'algorithme reste la même.

Marques déposées

Le garbage collection automatique nous permet de nous concentrer sur la création d'applications au lieu de perdre du temps sur la gestion de la mémoire. Cependant, il existe des compromis.

Utilisation de la mémoire

Étant donné que l'algorithme ne sait pas exactement quand la mémoire n'est plus nécessaire, une application JS peut utiliser plus de mémoire qu'elle n'en a réellement besoin.

Même si un objet est marqué comme poubelle, c'est au garbage collector de décider quand et si la mémoire allouée sera collectée.

如果你希望应用程序尽可能提高内存效率,那么最好使用低级语言。 但是请记住,这需要权衡取舍。

性能

收集垃圾的算法通常会定期运行以清理未使用的对象。

问题是我们开发人员不知道何时会回收。 收集大量垃圾或频繁收集垃圾可能会影响性能。然而,用户或开发人员通常不会注意到这种影响。

内存泄漏

在全局变量中存储数据,最常见内存问题可能是内存泄漏

在浏览器的 JS 中,如果省略varconstlet,则变量会被加到window对象中。

users = getUsers();
Copier après la connexion

在严格模式下可以避免这种情况。

除了意外地将变量添加到根目录之外,在许多情况下,我们需要这样来使用全局变量,但是一旦不需要时,要记得手动的把它释放了。

释放它很简单,把 null 给它就行了。

window.users = null;
Copier après la connexion

被遗忘的计时器和回调

忘记计时器和回调可以使我们的应用程序的内存使用量增加。 特别是在单页应用程序(SPA)中,在动态添加事件侦听器和回调时必须小心。

被遗忘的计时器

const object = {};
const intervalId = setInterval(function() {
  // 这里使用的所有东西都无法收集直到清除`setInterval`
  doSomething(object);
}, 2000);
Copier après la connexion

上面的代码每2秒运行一次该函数。 如果我们的项目中有这样的代码,很有可能不需要一直运行它。

只要setInterval没有被取消,则其中的引用对象就不会被垃圾回收。

确保在不再需要时清除它。

clearInterval(intervalId);
Copier après la connexion

被遗忘的回调

假设我们向按钮添加了onclick侦听器,之后该按钮将被删除。旧的浏览器无法收集侦听器,但是如今,这不再是问题。

不过,当我们不再需要事件侦听器时,删除它们仍然是一个好的做法。

const element = document.getElementById('button');
const onClick = () => alert('hi');

element.addEventListener('click', onClick);

element.removeEventListener('click', onClick);
element.parentNode.removeChild(element);
Copier après la connexion

脱离DOM引用

内存泄漏与前面的内存泄漏类似:它发生在用 JS 存储DOM元素时。

const elements = [];
const element = document.getElementById('button');
elements.push(element);

function removeAllElements() {
  elements.forEach((item) => {
    document.body.removeChild(document.getElementById(item.id))
  });
}
Copier après la connexion

删除这些元素时,我们还需要确保也从数组中删除该元素。否则,将无法收集这些DOM元素。

const elements = [];
const element = document.getElementById('button');
elements.push(element);

function removeAllElements() {
  elements.forEach((item, index) => {
    document.body.removeChild(document.getElementById(item.id));
    elements.splice(index, 1);
  });
}
Copier après la connexion

由于每个DOM元素也保留对其父节点的引用,因此可以防止垃圾收集器收集元素的父元素和子元素。

总结

在本文中,我们总结了 JS 中内存管理的核心概念。写这篇文章可以帮助我们理清一些我们不完全理解的概念。

希望这篇对你有所帮助,我们下期再见,记得三连哦!

原文地址:https://felixgerschau.com/javascript-memory-management/

作者:Ahmad shaded

译文地址:https://segmentfault.com/a/1190000037651993

更多编程相关知识,请访问:编程入门!!

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 de ce site Web
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

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Article chaud

R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
1 Il y a quelques mois By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Meilleurs paramètres graphiques
1 Il y a quelques mois By 尊渡假赌尊渡假赌尊渡假赌
Will R.E.P.O. Vous avez un jeu croisé?
1 Il y a quelques mois By 尊渡假赌尊渡假赌尊渡假赌

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

La disposition des objets C++ est alignée sur la mémoire pour optimiser l'efficacité de l'utilisation de la mémoire La disposition des objets C++ est alignée sur la mémoire pour optimiser l'efficacité de l'utilisation de la mémoire Jun 05, 2024 pm 01:02 PM

La disposition des objets C++ et l'alignement de la mémoire optimisent l'efficacité de l'utilisation de la mémoire : Disposition des objets : les données membres sont stockées dans l'ordre de déclaration, optimisant ainsi l'utilisation de l'espace. Alignement de la mémoire : les données sont alignées en mémoire pour améliorer la vitesse d'accès. Le mot clé alignas spécifie un alignement personnalisé, tel qu'une structure CacheLine alignée sur 64 octets, pour améliorer l'efficacité de l'accès à la ligne de cache.

Gestion de la mémoire C++ : allocateur de mémoire personnalisé Gestion de la mémoire C++ : allocateur de mémoire personnalisé May 03, 2024 pm 02:39 PM

Les allocateurs de mémoire personnalisés en C++ permettent aux développeurs d'ajuster le comportement d'allocation de mémoire en fonction des besoins. La création d'un allocateur personnalisé nécessite l'héritage de std::allocator et la réécriture des fonctions allocate() et deallocate(). Les exemples pratiques incluent : l’amélioration des performances, l’optimisation de l’utilisation de la mémoire et la mise en œuvre de comportements spécifiques. Lors de son utilisation, il faut veiller à éviter de libérer de la mémoire, à gérer l'alignement de la mémoire et à effectuer des analyses comparatives.

Défis et contre-mesures de la gestion de la mémoire C++ dans un environnement multithread ? Défis et contre-mesures de la gestion de la mémoire C++ dans un environnement multithread ? Jun 05, 2024 pm 01:08 PM

Dans un environnement multithread, la gestion de la mémoire C++ est confrontée aux défis suivants : courses de données, blocages et fuites de mémoire. Les contre-mesures incluent : 1. L'utilisation de mécanismes de synchronisation, tels que les mutex et les variables atomiques ; 2. L'utilisation de structures de données sans verrouillage ; 3. L'utilisation de pointeurs intelligents ; 4. (Facultatif) La mise en œuvre du garbage collection ;

Comment la gestion de la mémoire C++ interagit-elle avec le système d'exploitation et la mémoire virtuelle ? Comment la gestion de la mémoire C++ interagit-elle avec le système d'exploitation et la mémoire virtuelle ? Jun 02, 2024 pm 09:03 PM

La gestion de la mémoire C++ interagit avec le système d'exploitation, gère la mémoire physique et la mémoire virtuelle via le système d'exploitation, et alloue et libère efficacement la mémoire pour les programmes. Le système d'exploitation divise la mémoire physique en pages et extrait les pages demandées par l'application de la mémoire virtuelle selon les besoins. C++ utilise les opérateurs new et delete pour allouer et libérer de la mémoire, en demandant des pages de mémoire au système d'exploitation et en les renvoyant respectivement. Lorsque le système d'exploitation libère de la mémoire physique, il échange les pages de mémoire les moins utilisées vers la mémoire virtuelle.

Meilleures pratiques pour la gestion de la mémoire des fonctions Golang Meilleures pratiques pour la gestion de la mémoire des fonctions Golang Apr 26, 2024 pm 05:33 PM

Les meilleures pratiques de gestion de la mémoire dans Go incluent : éviter l'allocation/libération manuelle de mémoire (à l'aide d'un garbage collector) ; utiliser des pools de mémoire pour améliorer les performances lorsque les objets sont fréquemment créés/détruits en utilisant le comptage de références pour suivre le nombre de références aux données partagées ; pools de mémoire synchronisés sync.Pool gère en toute sécurité les objets dans des scénarios simultanés.

Mécanisme de comptage de références dans la gestion de la mémoire C++ Mécanisme de comptage de références dans la gestion de la mémoire C++ Jun 01, 2024 pm 08:07 PM

Le mécanisme de comptage de références est utilisé dans la gestion de la mémoire C++ pour suivre les références d'objets et libérer automatiquement la mémoire inutilisée. Cette technologie maintient un compteur de références pour chaque objet, et le compteur augmente et diminue lorsque des références sont ajoutées ou supprimées. Lorsque le compteur descend à 0, l'objet est libéré sans gestion manuelle. Cependant, les références circulaires peuvent provoquer des fuites de mémoire et la maintenance des compteurs de références augmente la surcharge.

Comment gérer l'utilisation de la mémoire dans les fonctions PHP ? Comment gérer l'utilisation de la mémoire dans les fonctions PHP ? Apr 26, 2024 pm 12:12 PM

Pour gérer l'utilisation de la mémoire dans les fonctions PHP : évitez de déclarer des variables inutiles ; utilisez des structures de données légères ; libérez les variables inutilisées ; optimisez le traitement des fonctions de chaîne, par exemple en évitant les boucles infinies et en utilisant des tableaux indexés ;

Gestion de la mémoire des fonctions golang et goroutine Gestion de la mémoire des fonctions golang et goroutine Apr 25, 2024 pm 03:57 PM

La mémoire des fonctions dans Go est transmise par valeur et n'affecte pas la variable d'origine. Goroutine partage la mémoire et sa mémoire allouée ne sera pas récupérée par GC tant que Goroutine n'aura pas terminé l'exécution. Des fuites de mémoire peuvent se produire en conservant une référence Goroutine terminée, en utilisant des variables globales ou en évitant les variables statiques. Pour éviter les fuites, il est recommandé d'annuler les Goroutines via les canaux, d'éviter les variables statiques et d'utiliser des instructions defer pour libérer des ressources.

See all articles