Від автора: слово колбек, один з найскладніших для розуміння аспектів JavaScript, часто згадується в контексті функцій і подій. Що таке колбэки, і як вони працюють?
Ви, швидше за все, вже знайомі з колбэками. Наприклад, вони часто зустрічаються в обробниках подій:
button.addEventListener. (“click”, function() {
… якась дія
})
Така callback-функція анонімна і є замиканням. На колбэки можна посилатися через вираження функцій або обгорткові функції.
Навіщо потрібні callback-функції?
JavaScript – мова програмування, що працює з подіями: код виконується в порядку виникнення подій, але результат обчислюється не обов’язково за порядком у коді. Тобто код:
function first() {
…do something that takes a lot of calculation…
console.log(“First”);
}
first();
Роздрукує слово First в консолі після обчислень. Я я спізнюся цю функцію і створю другу, яка буде виконуватися відразу ж:
function first() {
setTimeout(function() { console.log(“First”); }, 1000);
}
function second(){
console.log(“Second”);
}
first();
second();
Результат в консолі буде відрізнятися від очікуваного:
Second
First
Чому? Під час виконання JS знаходить функцію first() і виконує її. Потім без пауз він переходить на другу функцію і запускає її. JS ніколи не зупиняється і шукає, що йому ще виконати. Ось чому в сучасних браузерах він так швидко працює.
Важливо відзначити, що колбек – це лише певний спосіб оголошення функцій в JS. Явного типу callback-функції не існує. Колбэки з’явилися в ES5 (попередній JS стандарт) і JQuery. На даний момент вони вважаються нормальною технікою програмування.
Покращуємо колбек-функції
У випадку з першим прикладом з обробником події, ми чекали, поки завершиться подія click, і тільки потім виконували залишився код. Однак якщо ви робите щось одне, набагато краще буде замінити колбек на названу функцію:
function makeMenu() {
… do something …
}
button.addEventListener. (“click”, makeMenu);
Результат буде той же, але так код стає більш абстрактним, а функцію makeMenu тепер можна повторно використовувати в інших частинах скрипта. Виникає одна можлива проблема. Якщо у функцію додати параметри, функція може спрацьовувати миттєво і без події кліку:
function makeMenu(param1) {
console.log(“Clicked”);
}
button.addEventListener. (“click”, makeMenu(param1));
Результат в консолі без події кліку:
Clicked
Іншими словами, JS запускає подія без якої-небудь дії. Виправити це можна, повернувшись до формального запису колбек-функцій:
function makeMenu(param1) {
console.log(“Clicked”);
}
button.addEventListener. (“click”, function() { makeMenu(param1) } );
Або ж для параметрів можна використовувати .bind():
button.addEventListener. (“click”, function() { makeMenu.bind(null, param1) } );
Перший приклад можна скоротити за допомогою функції-стрілки в ES6:
button.addEventListener. (‘click’, () => makeMenu)
У наступній статті я більш детально розповім про функції-стрілки. Також у наступній статті я детально розберу .bind() і просунуті можливості колбек-функцій.
У вас може закрастися підозра, що зчіпка подій за допомогою декількох колбек-функцій може сильно ускладнити код JS і заплутати спадкування. Ви праві. На сайті Callback Hell ви знайдете кілька хороших порад по роботі зі зв’язкою подій. У наступних статтях ми будемо приділяти увагу цій проблемі.
Висновок
По суті, колбек-функції являють собою спосіб контролювати порядок виконання коду в JS, спосіб домогтися виконання коду в логічному порядку. Такі функції часто називають асинхронним JS: функція передається у вигляді параметра і каже «зроби це в майбутньому». Наскільки у майбутньому або умови виконання переданої функції описуються в колбек-функції. У ES6 такий підхід використовують для промисов.
JS пронизаний колбек-функціями, які є невід’ємною частиною мови. window.requestAnimationFrame() – приклад колбек-функції, яка виконується, як тільки браузера визначає, що він готовий до візуалізації контенту на екран, що забезпечує плавність анімації.
Постійна робота JS (завжди чекає події і миттєво реагує на все) також впливає на продуктивність, особливо часто-запускаються події типу прокрутки вікна, зміни розміру вікна при роботі з деякими полями типу range. Я покажу ці приклади у статті, де ми будемо штучно занижувати продуктивність браузера.
Подієвий характер JS частково контролюється такими поняттями, як замикання, область видимості і контекст, про які я розповім в окремих статтях.