Циклические ссылки
Циклические ссылки являются источником практически любой утечки. Обычно скриптовые движки нормально отрабатывают с циклическими ссылками при помощи собственных сборщиков мусора, однако из‑за некоторых неопределенностей их механизм эвристических правил может дать сбой. Одной из таких неопределенностей будет состояние DOM‑объекта, к которому имеет доступ текущая порция скрипта. Основной принцип в данном случае можно описать так:
Рис. 7.3 .Основной шаблон циклической ссылки
Утечка в таком шаблоне происходит из‑за особенностей учета DOM‑ссылок. Объекты скриптового движка удерживают ссылку на DOM‑элемент и ожидают, пока будут освобождены все внешние ссылки, чтобы освободить, в свою очередь, этот указатель на DOM‑элемент. В нашем случае у нас две ссылки на объект скрипта: внутри области видимости скриптового движка и от расширенного свойства DOM‑элемента. По окончанию своей работы скрипт освободит первую ссылку, но ссылка из DOM‑элемента никогда не будет освобождена, потому что ждет, что это сделает объект скрипта!
Наверное, первой же мыслью будет, что такой сценарий развития событий легко обнаружить и устранить, однако на практике представленный базовый случай является только вершиной айсберга. Может оказаться так, что циклическая ссылка находится в конце цепочки из 30 объектов, а обнаружить ее при этом крайне тяжело.
Стоит посмотреть, как данный шаблон будет выглядеть в HTML. Это может вызвать утечку, используя глобальную переменную и DOM‑объект, как показано ниже.
<script type="text/javascript">
var myGlobalObject;
function SetupLeak()
{
// Для начала создадим ссылку из скрипта на DOM‑элемент
myGlobalObject = document.getElementById("LeakedDiv");
// Потом установим ссылку из DOM на глобальную переменную
document.getElementById("LeakedDiv").expandoProperty =
myGlobalObject;
}
function BreakLeak()
{
document.getElementById("LeakedDiv").expandoProperty = null;
}
window.onload = SetupLeak;
window.onunload = BreakLeak;
</script>
Чтобы разрушить этот шаблон, можно использовать явное присвоение null тому свойству, которое «течет». Таким образом, при закрытии документа мы сообщаем скриптовому движку, что между DOM‑элементом и глобальной переменной нет больше никакой связи. В результате все ссылки будут очищены, и сам DOM‑элемент будет освобожден. В таком случае веб‑разработчик знает больше о внутренних отношениях между объектами, чем сам скрипт, и может поделиться этой информацией со скриптом.
Дата добавления: 2015-05-19; просмотров: 727;