Вызывает ли утечка памяти закрытие JavaScript с помощью ссылки this / self - PullRequest
8 голосов
/ 17 февраля 2012

Из того, что я понимаю об утечках памяти, ссылка на переменную вне области действия в замыкании приведет к утечке памяти.

Но также обычной практикой является создание "той" переменной, чтобы сохранить ссылку "эта" и использовать ее в закрытии, особенно для событий.

Итак, в чем же дело с такими вещами:

SomeObject.prototype.createImage = function(){
    var that = this,
        someImage = new Image();
    someImage.src = 'someImage.png';
    someImage.onload = function(){
        that.callbackImage(this);
    }
};

Разве это не добавит небольшую утечку в проект?

Ответы [ 3 ]

4 голосов
/ 17 февраля 2012

Да, да, это вызывает утечку памяти, по крайней мере, в некоторых браузерах (угадайте, какой).Это одна из наиболее веских причин доверять одной из различных доступных платформ и настраивать все ваши обработчики событий с помощью своих механизмов вместо прямого добавления обработчиков событий «DOM 0», подобных этому.

ИнтернетExplorer (по крайней мере, до 9, и, возможно, включая 9) имеет два внутренних механизма выделения памяти (по крайней мере): один для DOM и один для JavaScript (хорошо JScript).Они не понимают друг друга.Таким образом, даже если узел DOM освобожден, любая память закрытия, как в вашем примере, не будет освобождена.

edit - О, и причина, по которой я упоминаю фреймворки, состоит в том, что они обычно включают кодчтобы попытаться смягчить эту проблему.Избегание прикрепления чего-либо к свойствам узла DOM является одним из самых безопасных подходов.У всех браузеров, о которых стоит беспокоиться (включая древние версии IE), есть альтернативные способы присоединения обработчиков событий к узлам DOM, например.

1 голос
/ 17 февраля 2012

Снимок сделан в темноте, но я считаю, что:

someImage.onload = function(){
    that.callbackImage(this);
    someImage.onload = null
}

устранит "утечку памяти", оставленную that

1 голос
/ 17 февраля 2012

Было время, когда в IE циклические ссылки с элементами DOM (которые обычно образовывались замыканиями при назначении функции слушателю) вызывали утечки памяти, например,

function foo() {
  var someEl = document.getElementById('...');
  someEl.onclick = function() {...};
}

Однако я думаю, что ониисправлены или исправлены настолько, что если тестирование не показывает иное, их можно игнорировать.Есть также несколько способов избежать таких замыканий, поэтому, даже если они представляют собой проблему, их можно обойти (например, не создавать циклические ссылки с элементами DOM).

Редактировать

Использование библиотек или любого другого метода присоединения слушателей может по-прежнему создавать циклические ссылки и утечки памяти, например, в IE:

function foo() {
  var el = document.getElementById('d0');

  // Create circular reference through closure to el
  el.attachEvent('onclick', function(){bar(el);});

}

function bar(o) {
  alert(o == window.event.srcElement);  // true
}

window.onload = foo;

В приведенном выше примере attachEvent для добавления прослушивателя (что в значительной степени все фреймворки будут использовать для IE <9, включая jQuery), но при этом все еще создает циклическую ссылку, включающую элемент DOM, и поэтому будет течь в определенных версиях IE.Так что простое использование библиотеки <strong>не решит проблему , вам нужно понять причины и избежать их.

...