содержание
Введение
Некоторые языки, такие как C, имеют низкоуровневые собственные примитивы управления памятью, такие как malloc() и free(). Разработчики используют эти примитивы для явного выделения и освобождения памяти операционной системы.
Напротив, JavaScript автоматически выделяет память при создании переменных (объектов, строк) и автоматически освобождает память, когда эти переменные не используются.Этот процесс называетсявывоз мусора. Эта функция «автоматического» освобождения ресурсов вызвала много путаницы, заставив разработчиков JavaScript (и других языков высокого уровня) думать, что они не могут заботиться об управлении памятью. это большая ошибка
жизненный цикл памяти
Независимо от используемого языка программирования жизненный цикл памяти в основном одинаков:
- Выделить память: память выделяется операционной системой, позволяя программам ее использовать (при объявлении переменных, функций и объектов система автоматически выделяет для них память)
- Работа с памятью: чтение и запись внутри, манипулируя переменными в коде (т. е. используя переменные, функции и т. д.)
- Освободить память: когда она не используется, вы можете освободить память для перераспределения (память, которая больше не используется, автоматически освобождается механизмом сборки мусора).
JS-модель памяти
В JavaScript есть два типа пространства памяти:Память стека (стек)а такжекуча памяти (куча), и типы данных JavaScript также делятся на две категории, а именнобазовый тип данныха такжессылочный тип данных. Как эти типы данных хранятся в памяти?
说是JS内存模型其实不太准确,只是便于理解。由于JavaScript中的内存分配是由js引擎完成的,所以更准确的描述是js引擎的内存模型。
Основные типы данных и стековая память
Базовые типы данных в JS, эти значения имеют фиксированный размер, часто хранятся в памяти стека (кроме замыканий), а место для хранения выделяется системой автоматически. Мы можем напрямую манипулировать значениями, хранящимися в пространстве памяти стека, поэтому все основные типы данных — это доступ к данным по значению.Хранение и использование данных в памяти стека аналогичны структуре данных стека в структуре данных, следуя принцип «последний пришел — первый ушел».
Известные базовые типы данных:
Number、String、Null、Boolean、Undefiend、Symbol(ES6新增)
Чтобы просто понять способ доступа к стеку, мы можем проанализировать его по аналогии с коробкой для пинг-понга. Левая часть изображения ниже.
Этот шарик для пинг-понга хранится точно так же, как данные хранятся в стеке. Мяч для пинг-понга 5 в верхней части коробки нужно положить последним, но его можно использовать первым. И если мы хотим использовать нижний шарик для пинг-понга 1, мы должны вынуть 4 верхних шарика для пинг-понга, чтобы шарик для пинг-понга 1 оказался наверху коробки. Это пространство стекаФИФО, ЛИФОспециальность.
Справочные типы данных и динамическая память
В отличие от других языков, эталонные типы данных JS, такие как массивы, не имеют фиксированного размера. Значения ссылочных типов данных — это объекты, которые хранятся в куче памяти. JavaScript не допускает прямого доступа к местам в куче памяти, поэтому мы не можем напрямую манипулировать пространством кучи памяти объекта. Манипулируя объектом, вы на самом деле манипулируете ссылкой на объект, а не на сам объект. Следовательно, все значения ссылочных типов доступны по ссылке. Ссылку здесь можно приблизительно понимать как адрес, хранящийся в объекте переменных, который связан с фактическим значением памяти кучи.
Структура данных кучи представляет собой древовидную структуру. Способ доступа к данным очень похож на книжные полки и книги.
Известные типы справочных данных:
Object、Array、Date、RegExp、Function 等。
Чтобы лучше понять переменные объекты и память кучи, мы можем объединить следующие примеры и диаграммы для понимания.
var a1 = 0; // 变量对象
var a2 = 'this is string'; // 变量对象
var a3 = null; // 变量对象
var b = { m: 20 }; // 变量b存在于变量对象中,{m: 20} 作为对象存在于堆内存中
var c = [1, 2, 3]; // 变量c存在于变量对象中,[1, 2, 3] 作为对象存在于堆内存中
Поэтому, когда мы хотим получить доступ к ссылочному типу данных в памяти кучи, по сути, мы сначала получаем ссылку на адрес (или адресный указатель) объекта из объекта-переменной, а затем получаем нужные нам данные из памяти кучи.
После понимания пространства памяти JS мы можем использовать характеристики пространства памяти для проверки некоторых характеристик ссылочных типов.
Далее мы используем следующие примеры, чтобы углубить наше понимание памяти JS.
var a = 20;
var b = a;
b = 30;
var m = { a: 10, b: 20 };
var n = m;
n.a = 15;
Каково значение a в настоящее время? И каково значение m.a?
Когда данные в переменном объекте копируются, система автоматически присваивает новое значение новой переменной. После выполнения var b = a, хотя значения a и b оба равны 20, на самом деле они независимы и не зависят друг от друга. Конкретно как показано. Поэтому после того, как мы изменим значение b, значение a не изменится.
Копия ссылочного типа выполняется через var n = m. Копирование ссылочного типа также автоматически присваивает новое значение новой переменной и сохраняет его в объекте переменной, но отличие состоит в том, что это новое значение является просто адресным указателем ссылочного типа. Когда указатели адресов одинаковы, хотя они и независимы друг от друга, конкретный объект, доступ к которому осуществляется в переменном объекте, фактически один и тот же.
вывоз мусора
Сборка мусора — это механизм управления памятью, который своевременно освобождает память, которая больше не используется, чтобы предотвратить увеличение использования памяти, что приводит к зависаниям или даже к сбоям процесса. В JavaScript есть механизм сборки мусора, и его роль состоит в том, чтобы автоматически перерабатывать просроченные и недопустимые переменные.
Сборка мусора в памяти JavaScript выполняется автоматически движком js. Ключ к реализации сборки мусора заключается в том, как определить, не используется ли память больше, то есть является ли объект бесполезным. Есть два основных способа: подсчет ссылок и очистка меток.
Алгоритм сборки мусора
подсчет ссылок
Это старый механизм сборки мусора, используемый в IE6 и 7. Это самый простой алгоритм сборки мусора. Этот алгоритм упрощает определение того, «не нужен ли объект больше», поскольку «есть ли у объекта ссылки на него из других объектов». Если ссылок на объект нет (ноль ссылок), объект будет утилизирован механизмом сборки мусора.
var o1 = {
o2: {
x: 1
}
};
//2个对象被创建
/'o2'被'o1'作为属性引用
//谁也不能被回收
var o3 = o1; //'o3'是第二个引用'o1'指向对象的变量
o1 = 1; //现在,'o1'只有一个引用了,就是'o3'
var o4 = o3.o2; // 引用'o3'对象的'o2'属性
//'o2'对象这时有2个引用: 一个是作为对象的属性
//另一个是'o4'
o3 = '374'; //'o1'原来的对象现在有0个对它的引用
//'o1'可以被垃圾回收了。
//然而它的'o2'属性依然被'o4'变量引用,所以'o2'不能被释放。
o4 = null; //最初'o1'中的'o2'属性没有被其他的引用了
//'o2'可以被垃圾回收了
Циклические ссылки создают проблемыСуществует ограничение, когда речь идет о циклических ссылках. В приведенном ниже примере два объекта создаются и ссылаются друг на друга, создавая таким образом циклическую ссылку. Они выходят из области видимости после вызова функции и должны быть освобождены. Однако алгоритм подсчета ссылок учитывает, что на каждый из двух объектов ссылаются хотя бы один раз, и поэтому ни один из них не может быть собран.
function f() {
var o1 = {};
var o2 = {};
o1.p = o2; // o1 引用 o2
o2.p = o1; // o2 引用 o1\. 形成循环引用
}
f();
пометить и подметать
Принцип его работы упрощен: начните со сбора мусора корневого объекта (глобальной записи среды в JavaScript), отметьте все доступные объекты, а затем очистите все неотмеченные недостижимые объекты.
Этот алгоритм упрощает определение того, «не нужен ли объект больше», как и «доступен ли объект». Алгоритм состоит из следующих шагов.
- Сборщик мусора генерирует корневой список. Корень обычно является глобальной переменной, которая содержит ссылку в коде. В JavaScript объект окна — это глобальная переменная, которая может быть корневой.
- Все корни проверяются и помечаются как активные (не мусорные), а также рекурсивно проверяются все дочерние переменные. Все, что может прийти от корневого элемента, мусором не считается.
- Вся память, не помеченная как активная, считается мусором. Сборщик мусора может освободить память и вернуть ее операционной системе.
С 2012 года все браузеры имеют встроенные сборщики мусора, удаляющие метки.
утечка памяти
Утечка памяти — это, по сути, память, которая больше не нужна приложению и по какой-то причине не возвращается в операционную систему или в пул доступной памяти. Проще говоря: память, которая больше не используется и вовремя не освобождается, называется утечкой памяти.
Браузер Chrome для просмотра использования памяти
Следуйте инструкциям ниже
- Откройте панель «Производительность» инструментов разработчика браузера Chrome.
- Проверьте параметр «Память» на панели параметров.
- Нажмите кнопку записи в верхнем левом углу (кнопка с закрашенным кружком)
- Выполнение обычных операций на странице
- Через некоторое время нажмите «Стоп» и наблюдайте за данными на панели.
Дополнительные способы просмотра использования памяти,кликните сюда
4 распространенные утечки памяти в JavaScript
-
- неожиданная глобальная переменная
-
- Забытый таймер или обратный вызов
-
- Закрытие
-
- Ссылки вне DOM
Закрытие само по себе не приведет к утечке памяти, неправильно написанная программа вызовет утечку памяти или слишком много замыканий может легко привести к утечке памяти.
Конкретные детали КликКак работает JavaScript: управление памятью + как справиться с 4 распространенными утечками памяти