Шаблоны утечек
В следующих разделах мы обсудим общие шаблоны утечек памяти и приведем несколько примеров для каждого. Замечательным примером утечек будет случай замыкания в JScript, в качестве другого можно привести использование замыкания для обработки событий. При знакомстве с обработчиками событий можно будет легко найти и устранить многиe утечки памяти, однако другие случаи, связанные с замыканиями, могут остаться незамеченными.
Основные виды утечек можно разбить на следующие 4 типа.
Циклические ссылки, когда существует взаимная ссылка между DOM-объектом в браузере и скриптовым движком. Такие объекты могут приводить к утечкам памяти. Это самый распространенный шаблон.
Замыканияявляются самым значимым шаблоном для существующих архитектур веб-приложений. Замыкания довольно легко зафиксировать, потому что они зависят от ключевого слова, относящегося к используемому скриптовому языку, и могут быть по нему в общем случае обнаружены.
Постраничные утечкизачастую представляют собой очень маленькие утечки, которые возникают из-за учета объектов при перемещении от элемента к элементу. Ниже будет рассмотрен порядок добавления DOM-объектов, а заодно и характерные примеры, которые демонстрируют, как небольшое изменение вашего кода может предотвратить создание таких учитываемых объектов.
Псевдо-утечки, по существу, не являются утечками, но могут вызывать некоторое беспокойство, если не понимать, куда расходуется память. Будет рассмотрена перезапись объекта скрипта и как она проявляется в расходовании очень малого количества памяти, если работает так, как требуется.
Циклические ссылки
Циклические ссылки являются источником практически любой утечки. Обычно скриптовые движки нормально отрабатывают с циклическими ссылками при помощи собственных сборщиков мусора, однако из-за некоторых неопределенностей их механизм эвристических правил может дать сбой. Одной из таких неопределенностей будет состояние DOM-объекта, к которому имеет доступ текущая порция скрипта. Основной принцип в данном случае можно описать так:

Рис. 7.4 . Циклические ссылки с самозамыканием
В случае обычной циклической ссылки у нас есть 2 постоянных объекта, которые содержат ссылки друг на друга, — но замыкания отличаются от этой модели. Вместо создания прямых ссылок они наследуют информацию из пространства порождающих их объектов. В обычном случае локальные переменные в функции и используемые параметры существуют только в течение времени жизни самой функции. В случае замыканий эти переменные и параметры имеют внешнюю ссылку на весь период жизни замыкания, который может быть значительно дольше, чем у породившей ее функции.
В качестве примера можно рассмотреть Объект 2, который был бы освобожден по окончанию вызова функции, в общем случае. Однако после добавления замыкания была создана вторая ссылка на этот параметр, которая не может быть освобождена, пока не будет закрыто замыкание. Если вы прикрепили замыкание к событию, то вам придется его у события в конце концов убрать. Если замыкание прикреплено к расширенному параметру, нужно будет его занулить (приравнять этот параметр к null).
Замыкания создаются по вызову функции, поэтому два различных вызова породят два независимых замыкания, каждое будет содержать ссылки на параметры своего вызова. Из-за такой внешней прозрачности очень легко, на самом деле, позволить замыканиям «течь». В следующем примере приводится один из базовых случаев возникновения утечек при замыканиях:
function AttachEvents(element)
{
// Эта структура создает у элемента ссылку на ClickEventHandler
element.attachEvent("onclick",ClickEventHandler);
function ClickEventHandler()
{
// Это замыкание ссылается на элемент
}
}