Технопарк, весна, 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 datagen: 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 datagen: 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 datagen: 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 мс
requestAnimationFrameThrottling — декорирование функции при котором она будет выполняться не чаще одного раза в указанный период, даже если она будет вызвана много раз в течение этого периода. Т.е. все промежуточные вызовы будут игнорироваться
Debouncing — декоратор позволяет превратить несколько вызовов функции в течение определенного времени в один вызов, причем задержка начинает заново отсчитываться с каждой новой попыткой вызова
Приблизительно 50 % времени, которое тратится на вычисление стиля элемента, уходит на сопоставление селекторов, а вторую половину времени занимает построение RenderStyle (представления стиля) на основе сопоставленных правил
will-change, transform...transform, opacity