Просто для оновлення інформації тут. Я тестував різні браузери, зокрема щодо витоків пам'яті для циклічно залежних прослуховувачів подій на подіях iframe onload.
Використовуваний код (jsfiddle заважає тестуванню пам’яті, тому для перевірки використовуйте власний сервер):
<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() {
obj.increment += 1;
destroy();
};
}
function create() {
iframe = document.createElement('iframe');
generatedOnLoadEvent = createOnLoadFunction(iframe);
attachEvent(iframe, 'onload', generatedOnLoadEvent);
document.body.appendChild(iframe);
}
function destroy() {
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>
Якщо немає витоку пам'яті, використана пам'ять збільшиться приблизно на 1000 кб або менше після запуску тестів. Однак, якщо спостерігається витік пам'яті, пам'ять збільшиться приблизно на 16000 кб. Видалення прослуховувача подій спочатку завжди призводить до зменшення використання пам'яті (відсутність витоків).
Результати:
- IE6 - витік пам'яті
- IE7 - витік пам'яті
- IE8 - відсутність витоків пам'яті
- IE9 - витік пам'яті (???)
- IE10 - витік пам'яті (???)
- IE11 - відсутність витоків пам'яті
- Edge (20) - відсутність витоків пам'яті
- Chrome (50) - відсутність витоків пам'яті
- Firefox (46) - важко сказати, погано витікає, то, можливо, просто неефективний збирач сміття? Завершує додаткові 4 МБ без видимих причин.
- Opera (36) - відсутність витоків пам'яті
- Safari (9) - відсутність витоків пам'яті
Висновок: Кровотечі-додатки, ймовірно, можуть уникнути не видалення прослуховувачів подій. Але я все одно вважаю це гарною практикою, незважаючи на досаду.