Привет, 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, т.е. предыдущий объект.
Получается, что каждый новый объект ссылается на предыдущий, они образуют цепочку в памяти.
Если запустить этот код, то по этой логике будет утечка. В старых браузерах - обязательно будет.
Пруф:
![4c8a6c47b3764be1bc65e6a8df8cfed6.png](//habrastorage.org/files/4c8/a6c/47b/4c8a6c47b3764be1bc65e6a8df8cfed6.png)
Современные браузеры, конечно, умнее. 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:
![bdd1210bf5174a13bec4d27652124e70.png](//habrastorage.org/files/bdd/121/0bf/bdd1210bf5174a13bec4d27652124e70.png)
Пруф Chrome (цепочка объектов в памяти):
![f1da7a209bcb4012b89468907b3df274.png](//habrastorage.org/files/f1d/a7a/209/f1da7a209bcb4012b89468907b3df274.png)
Вот, собственно, и причина.