Qu'est-ce que la récupération de place JavaScript? Qu'est-ce qui est important pour un programmeur Web de comprendre le garbage collection JavaScript, afin d'écrire un meilleur code?
297
Qu'est-ce que la récupération de place JavaScript? Qu'est-ce qui est important pour un programmeur Web de comprendre le garbage collection JavaScript, afin d'écrire un meilleur code?
Réponses:
Eric Lippert a écrit un article de blog détaillé sur ce sujet il y a quelque temps (en le comparant également à VBScript ). Plus précisément, il a écrit sur JScript , qui est la propre implémentation d'ECMAScript par Microsoft, bien que très similaire à JavaScript. J'imagine que vous pouvez supposer que la grande majorité du comportement serait la même pour le moteur JavaScript d'Internet Explorer. Bien sûr, l'implémentation variera d'un navigateur à l'autre, bien que je soupçonne que vous pourriez prendre un certain nombre de principes communs et les appliquer à d'autres navigateurs.
Cité de cette page:
Le but principal de la récupération de place est de permettre au programmeur de ne pas se soucier de la gestion de la mémoire des objets qu'il crée et utilise, bien que, bien sûr, il ne soit pas possible de l'éviter parfois - il est toujours avantageux d'avoir au moins une idée approximative du fonctionnement de la récupération de place. .
Note historique: une révision antérieure de la réponse avait une référence incorrecte à l'
delete
opérateur. En JavaScript, l'delete
opérateur supprime une propriété d'un objet et est complètement différent dedelete
C / C ++.la source
delete
incorrectement; Par exemple, dans le premier exemple, au lieu dedelete foo
, vous devez d'abord supprimer l'écouteur d'événement viawindow.removeEventListener()
, puis utiliserfoo = null
pour remplacer la variable; dans IE,delete window.foo
(mais pasdelete foo
) aurait également fonctionné s'ilfoo
était global, mais même dans FF ou Operadelete
est un opérateur unaire (une expression), pas une instruction (ie:)delete 0, delete 0, delete 3
. Il ressemble à une déclaration lorsqu'il est exprimé par une déclaration d'expression.Méfiez-vous des références circulaires lorsque des objets DOM sont impliqués:
Modèles de fuite de mémoire en JavaScript
Gardez à l'esprit que la mémoire ne peut être récupérée qu'en l'absence de références actives à l'objet. Il s'agit d'un piège courant avec les fermetures et les gestionnaires d'événements, car certains moteurs JS ne vérifient pas quelles variables sont réellement référencées dans les fonctions internes et conservent simplement toutes les variables locales des fonctions englobantes.
Voici un exemple simple:
Une implémentation JS naïve ne peut pas être collectée
bigString
tant que le gestionnaire d'événements est présent. Il existe plusieurs façons de résoudre ce problème, par exemple la définitionbigString = null
à la fin deinit()
(delete
ne fonctionnera pas pour les variables locales et les arguments de fonction:delete
supprime les propriétés des objets et l'objet variable est inaccessible - ES5 en mode strict lancera même unReferenceError
si vous essayez pour supprimer une variable locale!).Je recommande d'éviter autant que possible les fermetures inutiles si vous vous souciez de la consommation de mémoire.
la source
Bonne citation tirée d'un blog
Le composant DOM est "récupéré", tout comme le composant JScript, ce qui signifie que si vous créez un objet dans l'un des composants, puis perdez la trace de cet objet, il sera finalement nettoyé.
Par exemple:
Lorsque vous appelez cette fonction, le composant JScript crée un objet (nommé bigArray) accessible dans la fonction. Cependant, dès que la fonction revient, vous "perdez la trace" de bigArray car il n'y a plus moyen de s'y référer. Eh bien, le composant JScript se rend compte que vous en avez perdu la trace, et donc bigArray est nettoyé - sa mémoire est récupérée. Le même genre de chose fonctionne dans le composant DOM. Si vous dites
document.createElement('div')
, ou quelque chose de similaire, le composant DOM crée un objet pour vous. Une fois que vous perdez la trace de cet objet d'une manière ou d'une autre, le composant DOM nettoiera le connexe.la source
Au meilleur de ma connaissance, les objets JavaScript sont régulièrement récupérés quand il n'y a plus de références à l'objet. C'est quelque chose qui se produit automatiquement, mais si vous voulez en savoir plus sur son fonctionnement, au niveau C ++, il est logique de jeter un œil au code source WebKit ou V8
En règle générale, vous n'avez pas besoin d'y penser, cependant, dans les navigateurs plus anciens, comme IE 5.5 et les premières versions d'IE 6, et peut-être les versions actuelles, les fermetures créeraient des références circulaires qui, si elles n'étaient pas cochées, finiraient par consommer de la mémoire. Dans le cas particulier que je veux dire sur les fermetures, c'est lorsque vous avez ajouté une référence JavaScript à un objet dom et un objet à un objet DOM qui renvoyait à l'objet JavaScript. Fondamentalement, il ne pourrait jamais être collecté et entraînerait finalement l'instabilité du système d'exploitation dans les applications de test qui faisaient une boucle pour créer des plantages. En pratique, ces fuites sont généralement petites, mais pour garder votre code propre, vous devez supprimer la référence JavaScript à l'objet DOM.
Habituellement, c'est une bonne idée d'utiliser le mot clé delete pour déréférencer immédiatement les gros objets tels que les données JSON que vous avez reçues et faire tout ce que vous devez en faire, en particulier dans le développement Web mobile. Cela provoque le prochain balayage du GC pour supprimer cet objet et libérer sa mémoire.
la source
mark-and-sweep
algorithmes de style plus récents s'en occupent .garbage collection (GC) est une forme de gestion automatique de la mémoire en supprimant les objets qui ne sont plus nécessaires.
tout processus traitant de la mémoire, procédez comme suit:
1 - allouez l'espace mémoire dont vous avez besoin
2 - faire un peu de traitement
3 - Libérez cet espace mémoire
il existe deux algorithmes principaux utilisés pour détecter quels objets ne sont plus nécessaires.
Collecte des ordures de comptage de références : cet algorithme réduit la définition de "un objet n'est plus nécessaire" à "un objet n'a aucun autre objet s'y référant", l'objet sera supprimé s'il n'y a pas de point de référence
Algorithme de marquage et de balayage : connectez chaque objet à la source racine. aucun objet ne se connecte à root ou à un autre objet. cet objet sera supprimé.
actuellement les navigateurs les plus modernes utilisant le deuxième algorithme.
la source
Tous les moteurs JavaScript ont leurs propres récupérateurs de place et peuvent différer. La plupart du temps, vous n'avez pas à vous occuper d'eux car ils font simplement ce qu'ils sont censés faire.
L'écriture d'un meilleur code dépend principalement de votre connaissance des principes de programmation, du langage et de l'implémentation particulière.
la source
vérifier ça
En Javascript, vous ne vous souciez pas de l'allocation de mémoire et de la désallocation. L'ensemble du problème est demandé à l'interpréteur Javascript. Des fuites sont toujours possibles en Javascript, mais ce sont des bugs de l'interpréteur. Si vous êtes intéressé par ce sujet, vous pouvez en lire plus sur www.memorymanagement.org
la source
Sur Windows, vous pouvez utiliser Drip.exe pour trouver des fuites de mémoire ou vérifier si votre routine mem gratuite fonctionne.
C'est vraiment simple, il suffit d'entrer une URL de site Web et vous verrez la consommation de mémoire du moteur de rendu IE intégré. Appuyez ensuite sur Actualiser, si la mémoire augmente, vous avez trouvé une fuite de mémoire quelque part sur la page Web. Mais cela est également très utile pour voir si les routines de libération de mémoire fonctionnent pour IE.
la source
Les types de référence ne stockent pas l'objet directement dans la variable à laquelle il est affecté, de sorte que la variable objet dans cet exemple ne contient pas réellement l'instance d'objet. Au lieu de cela, il contient un pointeur (ou une référence) vers l'emplacement en mémoire où l'objet existe
si vous affectez une variable à une autre, chaque variable obtient une copie du pointeur et toutes deux font toujours référence au même objet en mémoire.
des principes du JavaScript orienté objet - NICHOLAS C. ZAKAS
la source