Переменные ограничены функциями, а не если / else / for / while / etc. блоки. Каждый раз, когда вы звоните
fragment.appendChild((function() { ...
вы создаете новую функцию (новую область видимости). Эта новая функция ссылается на переменные i
и response
. Так что теперь i
и response
ограничены ОБА внешней функцией и новой функцией.
Этого недостаточно для утечки памяти. (i
и response
- это обычные переменные, которые выйдут из области видимости после выполнения новой функции)
НО, вы создаете элемент p
DOM в новой функции и ссылаетесь на него во внешней функции (вы возвращаете его в вызов fragment.appendChild
в качестве аргумента). Теперь подумайте об этом: у вас есть внешняя область действия fragment
, ссылающаяся на p
DOM, созданный из внутренней области действия, для которой нужно было использовать переменные i
и response
из внешней области действия, чтобы создать элемент DOM в первом место.
Объекты fragment
и p
DOM имеют ссылку друг на друга. Несмотря на ваши попытки обнулить счетчик ссылок путем обнуления указателей переменных, p=null
и fragment = null
не избавят от всех ссылок. У fragment
все еще есть ссылка на внутреннюю p
, которая все еще имеет ссылку на внешнюю переменную response
. Из-за этой оставшейся циклической зависимости две «области видимости» никогда не будут собираться мусором.
Кто-нибудь, пожалуйста, исправьте меня, если я допустил какие-либо ошибки.
Что касается решения, просто не используйте внутреннюю функцию!
fragment = document.createDocumentFragment();
for (var i = 0, var e = response.verses.length; i < e; i++)
{
var p = document.createElement('p');
p.setAttribute('lang', (response.unicode) ? 'ar' : 'en');
p.innerHTML = ((response.unicode) ? (response.surah + ':' + (i+1)).transliterate() : response.surah + ':' + (i+1)) + ' ' + insertTags(response.verses[i], '<a href="#" onclick="window.popup(this);return false;" class="match">', '</a>');
fragment.appendChild(p);
}
params[0].appendChild( fragment );