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.