Maison  >  Article  >  interface Web  >  Introduction aux compétences de gestion de la mémoire JavaScript_javascript

Introduction aux compétences de gestion de la mémoire JavaScript_javascript

WBOY
WBOYoriginal
2016-05-16 16:09:40906parcourir

Présentation

Les langages de bas niveau, tels que C, ont des primitives de gestion de mémoire de bas niveau, telles que malloc() et free(). Les primitives de mémoire de JavaScript, quant à elles, sont allouées lors de la création de variables (objets, chaînes, etc.) puis libérées « automatiquement » lorsqu'elles ne sont plus utilisées. Ce dernier est appelé garbage collection. Cet "automatique" prête à confusion et donne aux développeurs JavaScript (et autres langages de haut niveau) l'illusion qu'ils n'ont pas à penser à la gestion de la mémoire.

Cycle de vie de la mémoire

Quel que soit le langage de programmation, le cycle de vie de la mémoire est fondamentalement le même :

1. Allouez la mémoire dont vous avez besoin
2. Utilisez-le (lire, écrire)
3. Relâchez-le lorsqu'il n'est pas utilisé ps : Cela a la même signification que "mettre un éléphant au réfrigérateur"

Les première et deuxième parties du processus sont claires dans toutes les langues. La dernière étape est claire dans les langages de bas niveau, mais dans les langages de haut niveau comme JavaScript, la dernière étape n'est pas claire.

Allocation de mémoire JavaScript

Initialisation des variables

Afin de ne pas inquiéter les programmeurs concernant l'allocation, JavaScript complète l'allocation de mémoire lors de la définition des variables.

Copier le code Le code est le suivant :

var n = 123; // Allouer de la mémoire aux variables numériques
var s = "azerty"; // Donner le type de caractère

var o = {
une : 1,
b : nul
}; // Allouer de la mémoire pour l'objet et ses variables contenant

var a = [1, null, "abra"]; // Alloue de la mémoire pour le tableau et ses variables contenant (tout comme les objets)
fonction f(a){
renvoie un 2 ;
} // Allouer de la mémoire pour la fonction (objet appelable)

// Les expressions de fonction peuvent également allouer un objet
someElement.addEventListener('click', function(){
someElement.style.backgroundColor = 'bleu';
}, faux);

Allocation de mémoire via appel de fonction

Certains appels de fonction entraînent une allocation de mémoire d'objet :

Copier le code Le code est le suivant :

var d = nouvelle Date();
var e = document.createElement('div'); //Attribuer un élément DOM

Certaines méthodes allouent de nouvelles variables ou de nouveaux objets :

Copier le code Le code est le suivant :

var s = "azerty";
var s2 = s.substr(0, 3); // s2 est une nouvelle chaîne
//Comme la chaîne est un invariant, JavaScript ne peut pas allouer de mémoire, mais stocker uniquement la plage de 0 à 3.

var a = ["ouais ouais", "nan nan"];
var a2 = ["génération", "nan nan"];
var a3 = a.concat(a2); // Il y a quatre éléments dans le nouveau tableau qui connectent le tableau a et le tableau a2.

Utilisation des valeurs

Le processus d'utilisation des valeurs est en fait une opération de lecture et d'écriture de la mémoire allouée, ce qui signifie que vous pouvez écrire une variable ou la valeur d'attribut d'un objet, et même transmettre des paramètres de fonction.

Libérer la mémoire lorsqu'elle n'est plus nécessaire

La plupart des problèmes de gestion de la mémoire surviennent à ce stade. La tâche la plus difficile ici est de constater que la mémoire allouée n’est effectivement plus nécessaire. Cela oblige souvent le développeur à déterminer quelle partie de la mémoire du programme n'est plus nécessaire et à la libérer.

L'interpréteur de langage de haut niveau intègre un "garbage collector" dont la tâche principale est de suivre l'allocation et l'utilisation de la mémoire afin qu'elle puisse être automatiquement libérée lorsque la mémoire allouée n'est plus utilisée. Ce processus est une approximation, car savoir si un certain morceau de mémoire est nécessaire est indécidable (ne peut pas être résolu par un certain algorithme

).

Collecte des déchets

Comme mentionné ci-dessus, le problème de la recherche automatique si une certaine mémoire n'est "plus nécessaire" ne peut pas être déterminé. Par conséquent, les implémentations de garbage collection ne peuvent résoudre les problèmes généraux que dans une mesure limitée. Cette section explique les concepts nécessaires pour comprendre les principaux algorithmes de garbage collection et leurs limites.

Citation

Les algorithmes de garbage collection reposent principalement sur la notion de références. Dans le contexte de la gestion de la mémoire, si un objet a l'autorisation d'accéder à un autre objet (implicitement ou explicitement), on l'appelle un objet référençant un autre objet. Par exemple, un objet Javascript possède une référence à son prototype (une référence implicite) et une référence à ses propriétés (une référence explicite).

Ici, le concept d'« objet » n'est pas seulement un objet Javascript spécial, mais inclut également la portée de la fonction (ou portée lexicale globale).

Référence comptage collecte des ordures

Il s'agit de l'algorithme de collecte des ordures le plus simple. Cet algorithme simplifie la définition de « si l'objet n'est plus nécessaire » comme « si l'objet a d'autres objets qui le référencent ». S'il n'y a aucune référence pointant vers l'objet (zéro référence), l'objet sera récupéré par le mécanisme de garbage collection.

Par exemple

Copier le code Le code est le suivant :

var o = {
une : {
b:2
>
};
// Deux objets sont créés, l'un est référencé comme propriété de l'autre, et l'autre est affecté à la variable o
// Évidemment, aucun d'entre eux ne peut être collecté

var o2 = o; // La variable o2 est la deuxième référence à "cet objet"
o = 1; // Maintenant, la référence originale o de "cet objet" est remplacée par o2

var oa = o2.a; // Référence la propriété a de "cet objet"
// Maintenant, "cet objet" a deux références, l'une est o2 et l'autre est oa

o2 = "yo"; // L'objet d'origine n'a désormais aucune référence
// Il peut être ramassé
// Cependant, l'objet de son attribut a est toujours référencé par oa, il ne peut donc pas encore être recyclé

oa = null; // L'objet avec l'attribut a a désormais également une référence nulle
// Il peut être collecté

Limitation : référence circulaire

Une limitation de cet algorithme simple est que si un objet en référence un autre (formant une référence circulaire), il se peut qu'il ne soit "plus nécessaire", mais il ne sera pas recyclé.

Copier le code Le code est le suivant :

fonction f(){
var o = {};
var o2 = {};
o.a = o2; // o référence o2
o2.a = o; // o2 fait référence à o

renvoie "azerty";
>

f();
// Deux objets sont créés et se référencent mutuellement, formant une boucle
// Ils ne quitteront pas la portée de la fonction après avoir été appelés
// Ils ne sont donc plus utiles et peuvent être recyclés
// Cependant, l'algorithme de comptage de références prend en compte qu'elles ont toutes au moins une référence les unes aux autres, elles ne seront donc pas recyclées

Exemples pratiques

IE 6, 7 effectue un recyclage par comptage de références sur les objets DOM. Un problème courant pour eux est celui des fuites de mémoire :

Copier le code Le code est le suivant :

var div = document.createElement("div");
div.onclick = fonction(){
faireQuelquechose();
};
// Le div a une référence à l'attribut de gestion des événements onclick
// Le gestionnaire d'événements a également une référence au div accessible dans la portée de la fonction
// Cette référence circulaire empêchera les deux objets d'être récupérés

Algorithme de marquage et d'effacement

Cet algorithme simplifie la définition de « si l'objet n'est plus nécessaire » comme « si l'objet peut être obtenu ».

Cet algorithme suppose de mettre en place un objet appelé root (en Javascript, root est l'objet global). Périodiquement, le garbage collector démarrera à la racine, trouvera tous les objets référencés depuis la racine, puis trouvera les objets référencés par ces objets... En partant de la racine, le garbage collector trouvera tous les objets pouvant être obtenus et tous les objets qu'on ne peut pas obtenir.

Cet algorithme est meilleur que le précédent, car "objet avec référence nulle" est toujours introuvable, mais l'inverse n'est pas nécessairement vrai, référez-vous à "référence cyclique".

Depuis 2012, tous les navigateurs modernes utilisent l'algorithme de récupération de place Mark-and-Sweep. Toutes les améliorations apportées à l'algorithme de récupération de place JavaScript sont basées sur des améliorations apportées à l'algorithme de balayage de marquage et n'améliorent pas l'algorithme de balayage de marquage lui-même ni sa définition simplifiée de « si un objet n'est plus nécessaire ».

Les références circulaires ne sont plus un problème

Dans l'exemple ci-dessus, après le retour de l'appel de fonction, les deux objets ne peuvent pas être obtenus à partir de l'objet global. Ils seront donc récupérés par le garbage collector.
Dans le deuxième exemple, une fois que le div et ses gestionnaires d'événements sont inaccessibles depuis la racine, ils seront collectés par le garbage collector.

Limitations : les objets doivent être explicitement inaccessibles

Bien qu'il s'agisse d'une limitation, elle est rarement dépassée, c'est pourquoi en réalité peu de gens se soucient du mécanisme de collecte des ordures.

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