Введение
Языки низкого уровня, такие как C, имеют низкоуровневые примитивы управления памятью, такие как Malloc () и Free (). Примитивы памяти JavaScript, с другой стороны, выделяются, когда создаются переменные (объекты, строки и т. Д.), А затем «автоматически» освобождены, когда они больше не используются. Последнее называется коллекцией мусора. Этот «автоматический» запутывает и дает разработчикам JavaScript (и другие языки высокого уровня) иллюзию: они могут игнорировать управление памятью.
Жизненный цикл памяти
Независимо от того, какой язык программирования жизненный цикл памяти в основном одинаково:
1. Выделите необходимую память
2. Используйте его (читать, написать)
3. Выпустите PS: и «Поместите слона в холодильник».
Первые и вторые части процесса ясны на всех языках. Последний шаг ясен на языках низкого уровня, но на языках высокого уровня, таких как JavaScript, последний шаг не ясен.
Распределение памяти для JavaScript
Переменная инициализация
Чтобы не беспокоить программистов с проблемой распределения, JavaScript завершает распределение памяти при определении переменных.
Кода -копия выглядит следующим образом:
var n = 123; // выделять память на числовые переменные
var s = "Азерти"; // Дайте тип символа
var o = {
A: 1,
Б: Нуль
}; // выделять память для объектов и их содержащихся переменных
var a = [1, null, "бюстгальтер"]; // выделять память для массивов и их содержат переменные (например, объекты)
функция f (a) {
вернуть A + 2;
} // выделять память для функций (Callible Objects)
// выражения функций также могут назначить объект
cheyElement.addeventListener ('click', function () {
cheyElement.style.backgroundcolor = 'blue';
}, ЛОЖЬ);
Распределение памяти через вызовы функций
Некоторые вызовы функций приводят к распределению памяти объекта:
Кода -копия выглядит следующим образом:
var d = new Date ();
var e = document.createElement ('div'); // назначить элемент DOM
Некоторые методы назначают новые переменные или новые объекты:
Кода -копия выглядит следующим образом:
var s = "Азерти";
var s2 = s.substr (0, 3); // S2 - новая строка
// Поскольку строка является инвариантом, JavaScript может не распределять память, но она сохраняет только диапазон 0-3.
var a = ["ouais ouais", "nan nan"];
var a2 = [«поколение», "Nan nan"];
var a3 = a.concat (a2); // В новом массиве есть четыре элемента, которые присоединяются к массиву A и массиве A2.
Использование значений
Процесс использования значений на самом деле является операцией чтения и записи распределения памяти, что означает, что переменная или значение свойства объекта могут быть записаны, или даже параметры функции могут быть переданы.
Освобожден, когда память больше не нужна
Большинство проблем управления памятью на этом этапе. Самая сложная задача здесь - найти «выделенная память действительно не нужна». Часто разработчики определяют, какой кусок памяти в программе больше не нужен, и освободить ее.
Изумный интерпретатор на высоком уровне встроен с «коллекционером мусора», и его основная задача-отслеживать распределение и использование памяти, чтобы она была автоматически выпущена, когда выделенная память больше не используется. Этот процесс является приближением, потому что невозможно определить, необходимо ли определить определенную часть памяти (он не может быть решен с помощью некоторого алгоритма).
Утилизация мусора
Как упомянуто выше, вопрос автоматического поиска того, является ли некоторая память «больше не нужна», невозможно определить. Следовательно, реализация сбора мусора может решить только общие проблемы с ограничениями. В этом разделе будут объяснены необходимые концепции для понимания основных алгоритмов сбора мусора и их ограничений.
Цитировать
Алгоритмы сбора мусора в основном полагаются на концепцию ссылки. В среде, управляемой памятью, если у объекта есть разрешение на доступ к другому объекту (неявно или явно), он называется объектом, относящимся к другому объекту. Например, объект JavaScript имеет ссылку на его прототип (неявная ссылка) и ссылку на его свойства (явная ссылка).
Здесь концепция «объекта» не только специальных объектов JavaScript, но и функциональных областей (или глобальной лексической области).
Сборник мусора справочника
Это самый простой алгоритм сбора мусора. Этот алгоритм упрощает «не нужен ли объект», как «есть ли у объекта другие объекты, упомянутые на него». Если ссылаться на объект (нулевая ссылка), объект будет переработан с помощью механизма сбора мусора.
Например
Кода -копия выглядит следующим образом:
var o = {
A: {
B: 2
}
};
// созданы два объекта, один ссылается на атрибут другого, а другой присваивается переменной o
// Очевидно, ни один из них не может быть собран мусором
var o2 = o; // переменная O2 является второй ссылкой на «этот объект»
o = 1; // Теперь исходная ссылка o «этого объекта» заменяется O2
var oa = o2.a; // Ссылка на свойство «этот объект»
// Теперь есть две ссылки на «этот объект», один - O2, а другой - ОА
O2 = "yo"; // Оригинальный объект теперь нулевой ссылки
// он может быть переработан
// однако, объект его собственности A все еще ссылается OA, поэтому его еще нельзя переработать
oa = null; // объект с свойством A теперь также ссылается на ноль
// это может быть собрано мусором
Ограничение: переработка ссылки
Этот простой алгоритм имеет ограничение, что если объект относится к другому (образуя круговую ссылку), он может «больше не нуждаться в этом», но они не будут переработаны.
Кода -копия выглядит следующим образом:
функция f () {
var O = {};
var o2 = {};
OA = O2; // o Ссылка O2
o2.a = o; // o2 кавычки o
вернуть "азерти";
}
f ();
// создаются два объекта и ссылаются друг на друга, образуя петлю
// они не оставят сферу функции после вызова
// так они бесполезны и могут быть переработаны
// однако, алгоритм подсчета ссылок учитывает, что у них есть ссылки друг на друга, по крайней мере, один раз, поэтому они не будут переработаны
Практические примеры
IE 6, 7 Утилизация эталонного подсчета на объекты DOM. Для них общая проблема - утечки памяти:
Кода -копия выглядит следующим образом:
var div = document.createElement ("div");
div.onclick = function () {
dosomething ();
};
// Div имеет ссылку, указывающую на свойство обработки событий OnClick
// Обработка событий также имеет ссылку на DIV, к которому можно получить доступ в области функции
// Эта круговая ссылка приведет к собранному мусору, что оба объекта
Алгоритм для очистки от марки
Этот алгоритм упрощает «не нужен ли объект» как «доступен ли объект».
Этот алгоритм предполагает настройку объекта, называемого root (в JavaScript, root - это глобальный объект). Регулярно, коллекционер мусора начнется в корне, найдет все объекты, на которые ссылаются у корня, а затем найдут объекты, на которые ссылаются эти объекты ... начиная с корня, сборщик мусора найдет все объекты, которые могут быть получены, и все объекты, которые не могут быть получены.
Этот алгоритм лучше, чем предыдущий, потому что «объекты с нулевыми ссылками» всегда недоступны, но, наоборот, это не обязательно верно, см. «Циркулярные ссылки».
С 2012 года все современные браузеры использовали алгоритм сбора мусора с тегом. Все улучшения алгоритма сбора мусора JavaScript основаны на улучшении алгоритма очистки тегов, без улучшения самого алгоритма очистки тегов и его упрощенного определения того, не нужен ли объект.
Круговые ссылки больше не проблема
В приведенном выше примере после возврата вызова функции оба объекта не могут быть извлечены из глобального объекта. Поэтому они будут переработаны коллекционером мусора.
Второй пример также, как только DIV и его обработка событий не могут быть извлечены из корня, они будут переработаны коллекционером мусора.
Ограничение: объекты должны быть явно недоступны
Хотя это является ограничением, он редко разбивается, поэтому на самом деле мало кто заботится о механизме сбора мусора.