2014-06-14 2 views
1

Не думаю, что я полностью понимаю эту концепцию.Уточнение регрессионной циркулярной ссылки

Я понимаю, как имеющие вещи, которые требуют друг друга, приводит к бесконечному циклу, но я не вижу, как это происходит в некоторых примерах я рассматриваю

function setHandler() { 
    var elem = document.getElementById('id') 

    elem.onclick = function() { 
    // ... 
    } 
} 

Как это проблема? Я просто вижу, что элемент привязан к функции при нажатии.

Screenshot

Он говорит, что есть ссылка через внешний LexicalEnvironment - но не это происходит один раз?

Заранее спасибо.

+1

* «В нем говорится, что есть ссылка через внешнюю лексическую среду» * - Что такое «это»? (В коде, который вы показываете, нет ошибки, может быть, вы не показываете достаточно кода?) – Tomalak

+0

@Tomalak http://puu.sh/9sURX/010cde7034.png –

+0

А, это немного яснее. Я добавил изображение к вашему вопросу для справки. – Tomalak

ответ

0

JavaScript использует то, что называется лексической обзорное. Области применения

  • определить, какие переменные видимы в определенном контексте (следствие: они определяют, какие переменные не видны никому, и может быть мусора безопасно)
  • созданы для каждого function(каждый раз, когда вы используете ключевое слово, новый размах создается)
  • могут быть вложенными (потому что функции могут быть вложенными)
  • , сохраняются для каждой функции (при вызове функции гарантируется, что он может видеть все переменные во всех областях(), которые были доступны, когда он был создан!)

Это означает, что:

          // +- global scope 
              // | 
function setHandler() {      // |+- scope for setHandler() 
              // || sees: own, global 
    var elem = document.getElementById('id'); // || 
              // || 
    elem.onclick = function() {    // ||+- Scope for anonymous function 
    // ...         // ||| sees: own, setHandler, global 
    }           // ||| 
}           // || 
              // | 

Теперь анонимный функция, которую вы назначаете onclick, может видеть переменные elem и setHandler и все, что связано с глобальным охватом.

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

Теперь нельзя обработать функцию анонимного обработчика кликов, поскольку она содержит ссылку на elem (через область действия), которая, в свою очередь, содержит ссылку на анонимную функцию (через ее свойство onclick).Счетчик ссылок для обоих объектов остается равным 1, потому что два относятся друг к другу.

Примечание пункт-сверху: Область применения являются постоянными, так что «лексической среда» из setHandler() хранится в живой даже если выполнении программы уже покинуло эту функцию - потому что она необходима анонимной внутренней функция. (Это называется «замыканием» и является одним из краеугольных камней JS.)

Современные сборщики мусора могут определить эту ситуацию и очистить обработчик событий соответственно, но, в частности, старые версии, если IE плохо себя ведет и утечка памяти.

+0

Спасибо, я искал цикл в исполнении, ни один из них не очищался, поэтому я не мог понять, где формируется цикл. –

+0

A * круговая ссылка * не имеет никакого отношения к циклу. Вы имеете в виду «A звонки B, который называет A». Обычно это называется бесконечной рекурсией * и причиной ошибок переполнения стека. Это может случиться и с вызовами A A, а также A. – Tomalak

+0

хе-хе, stackoverflow, хорошо, еще раз спасибо. –

1

Как это проблема?

Это является серьезной проблема в более ранних версиях IE 6, как он создал «утечку памяти», потому что циклические ссылки, включающие элементы DOM привели к памяти не будет выпущена, когда страница была выгружена, поэтому они потребляли все больше и больше памяти, делая браузер менее отзывчивым. Там хорошая статья here.

В отношении конкретного шаблона в OP, круговая ссылка легко избежать:

function setHandler() { 
    var elem = document.getElementById('id') 

    elem.onclick = function() { 
    // ... 
    } 

    // Break circular reference 
    elem = null; 
} 
+0

Вы также можете сделать переменную global, объект окна, который содержит глобальные переменные, очищается в конце жизненного цикла страниц. – scragar

+0

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

+1

Поскольку слушатель элемента имеет ссылку на контекст выполнения * setHandler *, который имеет глобальный объект в своей цепочке областей видимости, который имеет ссылку на элемент (например, через идентификатор), который ссылается на слушателя. – RobG

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

  • Нет связанных вопросов^_^