Технопарк, весна, 2019 г.
JavaScript — это язык с автоматическим управлением памятью. В языке JavaScript память выделяется автоматически при создании объектов и освобождается тоже автоматически в процессе сборки мусора
Утечка памяти — ситуация, когда память занимается объектами, которые больше не нужны приложению, но которые не могут быть освобождены автоматически из-за несовершенства алгоритмов сборки мусора
Чаще всего причиной утечек памяти являются т.н. нежелательные ссылки — ссылки, достижимые из корня, но ссылающиеся на фрагменты памяти, которые точно никогда больше не понадобятся
Например, потерявшие актуальность переменные, забытые в коде и удерживающие в памяти ненужные более объекты
// неявное объявление переменных
function foo(arg) {
bar = 42; // будет создана глобальная переменная
}
foo();
// потеря контекста
const counter = {
num: 0,
inc() {
this.num ++;
},
}
setInterval(counter.inc, 1000); // ooops!
// закэшировали ссылки
window.elements = {
button: document.querySelector('button#inc'),
cell: document.querySelector('.js-super-table td.js-super-cell'),
};
// do stuff
// элементы будут удалены из DOM, но останутся в памяти
document.removeChild(window.elements.button);
document.removeChild(document.querySelector('.js-super-table'));
const trigger = document.getElementById('trigger');
const elementToRemove = document.getElementById('remove');
trigger.addEventListener('click', function () {
document.removeChild(elementToRemove);
});
// починить можно, например, так
const trigger = document.getElementById('trigger');
trigger.addEventListener('click', function () {
const elementToRemove = document.getElementById('remove');
document.removeChild(elementToRemove);
});
let state = { gen: 0 };
const updateState = function () {
const oldState = state;
state = {
data: new Array(1024 * 1024).join('*'), // 2 MB of data
gen: oldState.gen++,
};
};
updateButton.onclick = updateState;
let state = { gen: 0 };
const updateState = function () {
const oldState = state;
state = {
data: new Array(1024 * 1024).join('*'), // 2 MB of data
gen: oldState.gen++,
log() { console.log(this.gen) }, // here!
};
};
updateButton.onclick = updateState;
let state = { gen: 0 };
const updateState = function () {
const oldState = state;
const unused = function () {
if (oldState) { console.log('hello here') }
};
state = {
data: new Array(1024 * 1024).join('*'), // 2 MB of data
gen: oldState.gen++,
log() { console.log(this.gen) },
};
};
window.performance.memory
— объект MemoryInfoРазберём, как ими пользоваться на примере
Ещё больше примеров по ссылке на developer.chrome.com
Frontend-разработчик, знакомый с внутренним механизмом работы браузеров, принимает более квалифицированные решения и понимает, почему следует выбрать те или иные средства
Кроме того, это просто интересно 😎
go to item four
Сегодня большинство устройств обновляют свои экраны 60 раз в секунду. Каждый из этих кадров может длиться чуть более 16 мс (1 секунда / 60 = 16,66 мс). В реальности же браузеру нужно выполнить и еще кое-какие действия, потому непрерывная работа JS должна занимать не более 10 мс
requestAnimationFrame
Throttling — декорирование функции при котором она будет выполняться не чаще одного раза в указанный период, даже если она будет вызвана много раз в течение этого периода. Т.е. все промежуточные вызовы будут игнорироваться
Debouncing — декоратор позволяет превратить несколько вызовов функции в течение определенного времени в один вызов, причем задержка начинает заново отсчитываться с каждой новой попыткой вызова
Приблизительно 50 % времени, которое тратится на вычисление стиля элемента, уходит на сопоставление селекторов, а вторую половину времени занимает построение RenderStyle (представления стиля) на основе сопоставленных правил
will-change
, transform
...transform
, opacity