2014-02-21 4 views
9

Я читал о том, как circular references cause memory leaks in IE, но я был очень смущен на примере, используя замыкание в замыкании разорвать циклическую ссылку:Как двойные замыкания прерывают циркулярные ссылки?

function addHandler() { 
    var clickHandler = function() { 
     this.style.backgroundColor = 'red'; 
    }; 
    (function() { 
     var el = document.getElementById('el'); 
     el.onclick = clickHandler; 
    })(); 
} 

Моя голова получил все препирались с тем, что ссылки на то, что, которые являются замыканиями , которые являются объектами области. Может ли кто-то разбить его более явно, чем MDN? Благодарю.

ответ

8

Если у вас

function addHandler() { 
    var clickHandler = function() { 
     this.style.backgroundColor = 'red'; 
     // can access `el` here 
    }; 
    var el = document.getElementById('el'); 
    el.onclick = clickHandler; 
} 

затем el имеет ссылку на clickHandler, но clickHandler также имеет ссылку на el, потому что это замыкание. -> циклическая ссылка (в IE)

Вводя новую область, вы делаете elместного, так что он не доступен clickHandler, -> не циклическая ссылка.

function addHandler() { 
    var clickHandler = function() { 
     this.style.backgroundColor = 'red'; 
     // cannot access `el` here 
    }; 
    (function() { 
     // `el` is local to this immediately invoked function 
     var el = document.getElementById('el'); 
     el.onclick = clickHandler; 
    })(); 
} 

Таким образом, решение проблемы утечки памяти не ввести еще одно замыкания, это создать новой области, что «щиты» в ценности друг от друга (в одном направлении наименее).

+0

так что в первом примере, хотя в '' clickHandler' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' продолжалось в объекте объекта clickHandler'? Значение, даже если 'clickHandler' * может * ссылаться на' el', 'clickHandler' имеет доступ к ссылке' el' с явной ссылкой или без нее? Таким образом, создается круговая ссылка между 'el' в объекте области видимости clickHandler и' clickHandler' в объекте 'el'? Я просто хочу убедиться, что 'this' в' clickHandler' не вызывал циклическую ссылку на 'el', а не объект scope, делающий эту ссылку. –

+1

@TriNoensie: Нет, это не имеет никакого отношения к 'this'. Когда функция создается, она также получает ссылку на «область», в которой создается функция, т. Е. Имеет * неявную * ссылку на все переменные, которые также доступны в области, которую она создала. И это вызвало проблемы в IE. –

3

Эмпирические правила, что я хожу по:

Для закрытия JavaScript должен быть создан, должен быть вложен функции и внутренняя функция должна иметь доступ к или есть ссылка на силу (давайте просто скажем, «потрогать» для краткости) переменная во внешней функции. Если ни один из этих двух критериев не найден, в JavaScript нет закрытия.

Утечки утечки возникают, когда такая переменная (упомянутая в предыдущем параграфе) во внешней функции оказывается элементом DOM.

В статье Mozilla, давайте посетить первый пример:

function addHandler() { 
    var el = document.getElementById('el'); 
    el.onclick = function() { 
     this.style.backgroundColor = 'red'; 
    }; 
} 

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

Во втором примере, что вы в курсе,

function addHandler() { 
    var clickHandler = function() { 
     this.style.backgroundColor = 'red'; 
    }; 
    (function() { 
     var el = document.getElementById('el'); 
     el.onclick = clickHandler; 
    })(); 
} 

Там есть внешняя функция, и вложенными внутри этой внешней функции 2 вложенными (внутренние) функции, но они находятся на том же уровне, что означает один не является вложенные внутри другого. Вторая вложенная функция также имеет доступ к локальной переменной (clickHandler) во внешней функции, поэтому создается замыкание, которое создается. Тем не менее, утечки памяти отсутствуют, потому что эта локальная переменная (clickHandler) во внешней функции не является элементом DOM. Локальная переменная el не способствует утечке памяти, поскольку она локальна для второй вложенной функции и не определена во внешней функции addHandler().Другими словами, он является локальным для второй вложенной функции, он недоступен для первой вложенной функции, поэтому нет возможности утечки памяти.

Смежные вопросы