101 votes

Dois-je supprimer les écouteurs d'événements avant de supprimer les éléments ?

Si j'ai un élément parent avec des enfants qui ont des écouteurs d'événements liés à eux, dois-je supprimer ces écouteurs d'événements avant d'effacer le parent ? (c'est-à-dire parent.innerHTML = ''; ) Peut-il y avoir des fuites de mémoire si les écouteurs d'événements ne sont pas déliés d'un élément s'il est retiré du DOM ?

95voto

Dwight Points 221

Juste pour mettre à jour l'information ici. J'ai testé différents navigateurs, en particulier pour détecter les fuites de mémoire pour les écouteurs d'événements dépendants de manière circulaire sur les événements onload des iframes.

Le code utilisé (jsfiddle interfère avec les tests de mémoire, utilisez donc votre propre serveur pour le tester) :

<div>
    <label>
        <input id="eventListenerCheckbox" type="checkbox" /> Clear event listener when removing iframe
    </label>
    <div>
        <button id="startTestButton">Start Test</button>
    </div>
</div>

<div>
    <pre id="console"></pre>
</div>

<script>

    (function() {
        var consoleElement = document.getElementById('console');
        window.log = function(text) {
            consoleElement.innerHTML = consoleElement.innerHTML + '<br>' + text;
        };
    }());

    (function() {
        function attachEvent(element, eventName, callback) {
            if (element.attachEvent)
            {
                element.attachEvent(eventName, callback);
            }
            else
            {
                element[eventName] = callback;
            }
        }

        function detachEvent(element, eventName, callback) {
            if (element.detachEvent)
            {
                element.detachEvent(eventName, callback);
            }
            else
            {
                element[eventName] = null;
            }
        }

        var eventListenerCheckbox = document.getElementById('eventListenerCheckbox');
        var startTestButton = document.getElementById('startTestButton');
        var iframe;
        var generatedOnLoadEvent;

        function createOnLoadFunction(iframe) {
            var obj = {
                increment: 0,
                hugeMemory: new Array(100000).join('0') + (new Date().getTime()),
                circularReference: iframe
            };

            return function() {
                // window.log('iframe onload called');
                obj.increment += 1;
                destroy();
            };
        }

        function create() {
            // window.log('create called');
            iframe = document.createElement('iframe');

            generatedOnLoadEvent = createOnLoadFunction(iframe);
            attachEvent(iframe, 'onload', generatedOnLoadEvent);

            document.body.appendChild(iframe);
        }

        function destroy() {
            // window.log('destroy called');
            if (eventListenerCheckbox.checked)
            {
                detachEvent(iframe, 'onload', generatedOnLoadEvent)
            }

            document.body.removeChild(iframe);
            iframe = null;
            generatedOnLoadEvent = null;
        }

        function startTest() {
            var interval = setInterval(function() {
                create();
            }, 100);

            setTimeout(function() {
                clearInterval(interval);
                window.log('test complete');
            }, 10000);
        }

        attachEvent(startTestButton, 'onclick', startTest);
    }());

</script>

S'il n'y a pas de fuite de mémoire, la mémoire utilisée augmentera d'environ 1000kb ou moins après l'exécution des tests. En revanche, s'il y a une fuite de mémoire, la mémoire augmentera d'environ 16 000 Ko. La suppression de l'écouteur d'événements en premier entraîne toujours une utilisation de la mémoire plus faible (pas de fuite).

Résultats :

  • IE6 - fuite de mémoire
  • IE7 - fuite de mémoire
  • IE8 - pas de fuite de mémoire
  • IE9 - fuite de mémoire ( ???)
  • IE10 - fuite de mémoire ( ???)
  • IE11 - pas de fuite de mémoire
  • Edge (20) - pas de fuite de mémoire
  • Chrome (50) - pas de fuite de mémoire
  • Firefox (46) - difficile à dire, il n'y a pas de fuite importante, donc peut-être juste un ramasse-miettes inefficace ? Finit avec 4MB supplémentaires sans raison apparente.
  • Opera (36) - pas de fuite de mémoire
  • Safari (9) - pas de fuite de mémoire

Conclusion : Les applications de pointe peuvent probablement s'en sortir en ne supprimant pas les écouteurs d'événements. Mais je considère que c'est une bonne pratique, malgré le désagrément.

57voto

elusive Points 14184

Réponse courte : oui

Longue réponse : La plupart des navigateurs gèrent cela correctement et suppriment eux-mêmes ces gestionnaires. Certains navigateurs plus anciens (IE 6 et 7, si je me souviens bien) provoquent des problèmes. Oui, il peut y avoir des fuites de mémoire. Vous ne devriez pas avoir à vous en préoccuper, mais vous devez le faire. Jetez un coup d'œil à ce document .

0 votes

En effet, bien que la plupart des navigateurs actuels n'en souffrent pas tant que cela, IE 7 est encore couramment utilisé. Jetez également un coup d'œil à Fuites de mémoire en JavaScript .

8 votes

Y a-t-il quelqu'un d'assez bien informé pour mettre à jour ce document pour le marché actuel des navigateurs ? Ou est-ce que cela mérite une question séparée ? Je pensais que IE7 était pratiquement éliminé alors que ie8 est toujours dans les parages. IE8 gère-t-il les écouteurs d'événements abandonnés ?

37 votes

6 ans plus tard, je pense IE < 10 peut être considéré sans risque comme déprécié et non utilisé par quiconque se rend sur des sites autres que Yahoo et AOL à ce stade. De toute façon, toute personne qui utilise IE de manière non sincère est probablement plus susceptible d'être victime d'une arnaque téléphonique indienne ou de contracter un virus que d'avoir des problèmes avec des gestionnaires d'événements qui ralentissent son navigateur.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X