Что такое сборка мусора в JavaScript? Что важно для веб-программиста, чтобы понять, что такое сборка мусора в JavaScript, чтобы лучше писать код?
Что такое сборка мусора в JavaScript? Что важно для веб-программиста, чтобы понять, что такое сборка мусора в JavaScript, чтобы лучше писать код?
Ответы:
Эрик Липперт написал подробное сообщение в блоге на эту тему некоторое время назад (дополнительно сравнивая его с VBScript ). Точнее, он написал о JScript , который является собственной реализацией ECMAScript от Microsoft, хотя и очень похож на JavaScript. Я полагаю, что вы можете предположить, что подавляющее большинство поведения будет таким же для движка JavaScript Internet Explorer. Конечно, реализация будет отличаться от браузера к браузеру, хотя я подозреваю, что вы могли бы взять ряд общих принципов и применить их к другим браузерам.
Цитируется с этой страницы:
В JScript используется сборщик мусора с разметкой разметки. Это работает так:
Каждая переменная, которая находится "в области видимости", называется "мусорщиком". Мусорщик может ссылаться на число, объект, строку, что угодно. Мы поддерживаем список мусорщиков - переменные перемещаются в список scav, когда они входят в область видимости, и из списка scav, когда они выходят из области видимости.
Время от времени работает сборщик мусора. Сначала он ставит «метку» на каждый объект, переменную, строку и т. Д. - всю память, отслеживаемую GC. (JScript использует внутреннюю структуру данных VARIANT, и в этой структуре есть множество дополнительных неиспользуемых битов, поэтому мы просто устанавливаем один из них.)
Во-вторых, он очищает отметку на мусорщиках и переходное закрытие ссылок мусорщиков. Таким образом, если объект мусорщика ссылается на объект некавенджера, то мы очищаем биты на некавенгере и на всем, на что он ссылается. (Я использую слово «закрытие» в другом смысле, чем в моем предыдущем посте.)
На данный момент мы знаем, что вся помеченная память - это выделенная память, которая не может быть достигнута ни одним путем из любой переменной в области видимости. Все эти объекты проинструктированы снести себя, что уничтожает любые циклические ссылки.
Основная цель сборки мусора состоит в том, чтобы позволить программисту не беспокоиться об управлении памятью объектов, которые они создают и используют, хотя, конечно, иногда этого не избежать - всегда полезно иметь хотя бы приблизительное представление о том, как работает сборка мусора. ,
Историческая справка: более ранняя редакция ответа содержала неверную ссылку на delete
оператора. В JavaScript оператор удаляет свойство из объекта , и полностью отличается в C / C ++.delete
delete
delete
неправильно; например, в первом примере вместо delete foo
, вы должны сначала удалить прослушиватель событий через, window.removeEventListener()
а затем использовать foo = null
для перезаписи переменной; в IE delete window.foo
(но не delete foo
) также работало бы, если бы оно foo
было глобальным, но даже тогда это не сработало бы в FF или Opera
delete
- это унарный оператор (выражение), а не оператор (то есть:) delete 0, delete 0, delete 3
. Это выглядит как выражение, когда оно выражено выражением выражения.
Остерегайтесь циклических ссылок, когда задействованы объекты DOM:
Шаблоны утечки памяти в JavaScript
Имейте в виду, что память может быть восстановлена только тогда, когда нет активных ссылок на объект. Это распространенная ошибка с замыканиями и обработчиками событий, так как некоторые движки JS не проверяют, на какие переменные действительно ссылаются внутренние функции, а просто сохраняют все локальные переменные включающих функций.
Вот простой пример:
function init() {
var bigString = new Array(1000).join('xxx');
var foo = document.getElementById('foo');
foo.onclick = function() {
// this might create a closure over `bigString`,
// even if `bigString` isn't referenced anywhere!
};
}
Наивная реализация JS не может собирать, bigString
пока существует обработчик событий. Есть несколько способов решить эту проблему, например, установка bigString = null
в конце init()
( delete
не будет работать для локальных переменных и аргументов функций: delete
удаляет свойства из объектов, а объект переменной недоступен - ES5 в строгом режиме даже выдаст a, ReferenceError
если вы попытаетесь удалить локальную переменную!).
Я рекомендую по возможности избегать ненужных замыканий, если вы заботитесь о потреблении памяти.
Хорошая цитата взята из блога
Компонент DOM является «сборщиком мусора», как и компонент JScript, что означает, что если вы создадите объект в любом из компонентов, а затем потеряете отслеживание этого объекта, он в конечном итоге будет очищен.
Например:
function makeABigObject() {
var bigArray = new Array(20000);
}
Когда вы вызываете эту функцию, компонент JScript создает объект (с именем bigArray), который доступен внутри функции. Однако, как только функция возвращается, вы теряете отслеживание bigArray, потому что больше нет возможности ссылаться на него. Ну, компонент JScript понимает, что вы потеряли его, и поэтому bigArray очищается - его память освобождается. То же самое работает в компоненте DOM. Если вы говорите document.createElement('div')
, или что-то подобное, то компонент DOM создает объект для вас. Как только вы как-то потеряете отслеживание этого объекта, компонент DOM очистит связанный.
Насколько я знаю, объекты JavaScript периодически собираются, когда на объект не остается ссылок. Это происходит автоматически, но если вы хотите узнать больше о том, как это работает, на уровне C ++ имеет смысл взглянуть на исходный код WebKit или V8.
Как правило, вам не нужно думать об этом, однако в старых браузерах, таких как IE 5.5 и более ранние версии IE 6, и, возможно, в текущих версиях, замыкания будут создавать циклические ссылки, которые, если их не проверять, в конечном итоге израсходуют память. В конкретном случае, когда я имею в виду замыкания, это было, когда вы добавили ссылку JavaScript на объект dom и объект на объект DOM, который ссылался на объект JavaScript. По сути, его никогда не удастся собрать, и в конечном итоге ОС станет нестабильной в тестовых приложениях, которые зацикливаются для создания сбоев. На практике эти утечки обычно невелики, но для поддержания чистоты кода необходимо удалить ссылку JavaScript на объект DOM.
Обычно хорошей идеей является использование ключевого слова delete для немедленной отмены ссылки на большие объекты, такие как данные JSON, которые вы получили назад и сделали с ними все, что вам нужно, особенно в разработке для мобильных устройств. Это приводит к следующей очистке GC, чтобы удалить этот объект и освободить его память.
mark-and-sweep
алгоритмы стиля заботятся об этом .
сборщик мусора (GC) - это форма автоматического управления памятью, удаляющая ненужные объекты.
любой процесс, связанный с памятью, выполните следующие действия:
1 - выделите необходимое пространство памяти
2 - сделать некоторую обработку
3 - освободить это пространство памяти
Есть два основных алгоритма, которые используются для определения того, какие объекты больше не нужны.
Сборка мусора с подсчетом ссылок : этот алгоритм сокращает определение «объект больше не нужен» до «у объекта нет ссылок на него», объект будет удален, если на него не будет ссылки
Алгоритм разметки и свипирования : соедините каждый объект с корневым источником. любой объект не соединяется с корнем или другим объектом. этот объект будет удален.
В настоящее время большинство современных браузеров используют второй алгоритм.
«В информатике сборщик мусора (GC) - это форма автоматического управления памятью. Сборщик мусора, или просто сборщик, пытается вернуть мусор или память, используемую объектами, которые никогда не будут доступны приложению».
Все движки JavaScript имеют свои собственные сборщики мусора, и они могут отличаться. В большинстве случаев вам не нужно иметь с ними дело, потому что они просто делают то, что должны делать.
Написание лучшего кода в основном зависит от того, насколько хорошо вы знаете принципы программирования, язык и особенности реализации.
Что такое сборка мусора в JavaScript?
проверить это
Что важно для веб-программиста, чтобы понять, что такое сборка мусора в JavaScript, чтобы лучше писать код?
В Javascript вы не заботитесь о выделении и освобождении памяти. Вся проблема требует интерпретатор Javascript. Утечки все еще возможны в Javascript, но они являются ошибками интерпретатора. Если вы заинтересованы в этой теме, вы можете прочитать больше на www.memorymanagement.org
В Windows вы можете использовать Drip.exe, чтобы найти утечки памяти или проверить, работает ли ваша бесплатная программа mem.
Это действительно просто, просто введите URL веб-сайта, и вы увидите потребление памяти встроенным IE рендерером. Затем нажмите обновить, если память увеличивается, вы обнаружили утечку памяти где-то на веб-странице. Но это также очень полезно, чтобы увидеть, работают ли подпрограммы для освобождения памяти для IE.
Ссылочные типы не сохраняют объект непосредственно в переменной, которой он назначен, поэтому переменная объекта в этом примере фактически не содержит экземпляр объекта. Вместо этого он содержит указатель (или ссылку) на место в памяти, где существует объект
var object = new Object();
если вы назначаете одну переменную другой, каждая переменная получает копию указателя, и обе по-прежнему ссылаются на один и тот же объект в памяти.
var object1 = new Object();
var object2 = object1;
JavaScript - это язык для сборки мусора , поэтому вам не нужно беспокоиться о распределении памяти при использовании ссылочных типов. Однако лучше разыменовать объекты, которые вам больше не нужны, чтобы сборщик мусора мог освободить эту память. Лучший способ сделать это - установить для переменной объекта значение null.
var object1 = new Object();
// do something
object1 = null; // dereference
Разыменование объектов особенно важно в очень больших приложениях, которые используют миллионы объектов.
из принципов объектно-ориентированного JavaScript - НИКОЛАЙ С. ЗАКАС