Привет, 3y3 :)
Чтобы проще было разобраться в этом примере - посмотрим вначале на более простой.
var theThing = null;
var replaceThing = function () {
var priorThing = theThing;
theThing = {
longStr: new Array(1000000).join('*'), // создаем 1Mб объект
someMethod: function () {
console.log("Hi, JS-dude!")
}
};
};
setInterval(replaceThing, 1000); // вызываем 'replaceThing' каждую секунду
Здесь при каждом вызове в theThing записывается новый объект, у которого функция someMethod, через замыкание, хранит ссылку на внешнюю область видимости, включающую в себя priorThing, т.е. предыдущий объект.
Получается, что каждый новый объект ссылается на предыдущий, они образуют цепочку в памяти.
Если запустить этот код, то по этой логике будет утечка. В старых браузерах - обязательно будет.
Пруф:
Современные браузеры, конечно, умнее. FF и Chrome увидят, что переменная priorThing не используется и удалят её из памяти, так что старый объект благополучно умрёт.
Чтобы этого не происходило, в исходном примере сделан "финт ушами": переменная используется в некой функции unused:
var theThing = null;
var replaceThing = function () {
var priorThing = theThing;
///////////////////
var unused = function() {
console.log(priorThing);
};
///////////////////
...
}
setInterval(replaceThing, 1000); // вызываем 'replaceThing' каждую секунду
Несовершенство сборщика мусора (3y3, видимо, лучшего мнения о нём) приводит к тому, что в этом случае сборщик мусора "не просекает", что переменная-то ненужная, и очистки не происходит.
Пруф Firefox:
Пруф Chrome (цепочка объектов в памяти):
Вот, собственно, и причина.