Стрілочні функці — нова форма запису анонімних функцій, що з'явилася в ES6. В чому ж переваги такого запису? Їх декілька.
1. Коротший синтаксис
Подивіться на цей приклад:
function funcName(params) {
return params + 2;
}
funcName(2);
// 4
Цей код досить роздутий: забагато символів для маленької функції. Нова форма запису дозволяє скоротити кількість зайвих символів.
var funcName = (params) => params + 2
funcName(2);
// 4
Круто, чи не так? Це досить абстрактний приклад, але, думаю, ви зрозуміли про що я. Давайте розглянемо загальний синтаксис:
(parameters) => { statements }
Якщо параметрів немає, то конструкція стає трохи коротшою.
() => { statements }
А якщо параметр один, то круглі дужки можна опустити:
parameters => { statements }
І остання фіча: якщо вам потрібно повернути значення, ми опускаємо фігурні дужки:
parameters => expression
// еквівалентно цьому
function (parameters){
return expression;
}
Добре, а як щодо практики? Відкрийте консоль Chrome (Windows: Ctrl + Shift + J; Mac: Cmd + Option + J) і введіть наступний код:
var double = num => num * 2
Ми присвоюємо змінній стрілочну функцію, яка приймає один аргумент, тому ми опустили круглі дужки. Також вона повинна повертати значення, тому ми прибрали фігурні дужки. Ось так вона працює:
double(2);
// 4
double(3);
// 6
2. Не змінює this
Перш ніж ми рушимо далі, ви повинні розуміти що таке this
і як він працює. Якщо ви ще не знайомі з ним, то вам допоможе ось цей пост.
На відміну від звичайної функції, стрілочна функція не змінює значення this
, тобто this
береться з контексту виконання функції.
Давайте розглянемо все на прикладі: створимо функцію-конструктор і створимо конкретний екземпляр:
function Counter() {
this.num = 0;
}
var a = new Counter();
Як ви знаєте, в конструкторі this
вказує на екземпляр, що створюється, в даному випадку — a
. Саме тому ми можемо вивести console.log(a.num)
і побачити 0
.
А що, якщо ми хочемо кожну секунду збільшувати значення a.num
? Ми можемо використовувати функцію setInterval()
, вона виконує задану функцію через фіксовані проміжки часу. Давайте додамо її до нашого конструктора:
function Counter() {
this.num = 0;
this.timer = setInterval(function add() {
this.num++;
console.log(this.num);
}, 1000);
}
Виглядає непогано. Ми додали функцію setInterval
, що кожну секунду (1000 мілісекунд) збільшує значення this.num
на одиницю і виводить значення в консоль. Давайте запустимо. І ось така несподіванка чекає нас в консолі:
var b = new Counter();
// NaN
// NaN
// NaN
// ...
Як ми бачимо, в консоль щось виводиться, але зовсім не те, що б нам хотілося бачити. Виводиться NaN
(Not a Number), давайте розбиратися що пішло не так. Перш за все, зупиніть наш таймер:
clearInterval(b.timer);
Давайте повернемося до коду. setInterval
виконується не на об'єкті. Також ми не викликаємо її за допомогою ключового слова new
, ми не використовуємо call
, bind
чи apply
, це звичайна функція. Схоже, this
вказує на глобальний об'єкт. Давайте перевіримо нашу теорію:
function Counter() {
this.num = 0;
this.timer = setInterval(function add() {
console.log(this);
}, 1000);
}
var b = new Counter();
Дійсно, в консоль щосекунди виводиться об'єкт window
. Знову зупиніть таймер і продовжимо:
clearInterval(b.timer);
Повернемося до нашої функції, вона виводить NaN
тому що this.num
вказує на window.num
, який не існує.
Як нам це виправити? За допомогою функцій-стрілок! Вони не змінюються this
, а беруть його з контексту. Давайте перепишемо наш код з використанням них:
function Counter() {
this.num = 0;
this.timer = setInterval(() => {
this.num++;
console.log(this.num);
}, 1000);
}
var b = new Counter();
// 1
// 2
// 3
// ...
Як бачите, все добре працює, this
вказує куди потрібно. Зупинити таймер можна так:
clearInterval(b.timer);
Ще немає коментарів