Повернемося до стрілкових функцій.
Стрілкові функції – це не просто «скорочення» для написання усіляких дрібниць. Вони мають деякі дуже специфічні та корисні особливості.
При написанні JavaScript-коду часто виникають ситуації, коли потрібно написати невелику функцію, яка буде виконана десь ще.
Наприклад:
arr.forEach(func)
–func
виконуєтьсяforEach
для кожного елемента масиву.setTimeout(func)
–func
виконується вбудованим планувальником.- …тощо.
Створення функції та передача її кудись – це в дусі JavaScript.
І в таких функціях ми зазвичай не хочемо виходити з поточного контексту. В таких випадках і корисні стрілкові функції.
Стрілкові функції не мають “this”
Як ми пам’ятаємо з розділу Методи об’єкта, "this", стрілкові функції не мають this
. Якщо відбувається звернення до this
, його значення береться ззовні.
Наприклад, ми можемо використовувати це для ітерації всередині методу об’єкта:
let group = {
title: "Наша група",
students: ["Іван", "Петро", "Марія"],
showList() {
this.students.forEach(
student => alert(this.title + ': ' + student)
);
}
};
group.showList();
Тут у forEach
використовується стрілкова функція, тому this.title
у ній має таке ж саме значення, як і у методі showList
, – group.title
.
Якби ми використали “звичайну” функцію, була б помилка:
let group = {
title: "Наша група",
students: ["Іван", "Петро", "Марія"],
showList() {
this.students.forEach(function(student) {
// Error: Cannot read property 'title' of undefined
alert(this.title + ': ' + student);
});
}
};
group.showList();
Помилка виникає через те, що forEach
запускає функції з this=undefined
за замовчуванням, тому ми намагаємося звернутися до undefined.title
.
Це не впливає на стрілкові функції, тому що вони не мають власного this
.
new
Відсутність this
призводить до ще одного обмеження: стрілкові функції не можуть бути використані як конструктори. Їх не можна викликати з new
.
Між стрілковою функцією =>
та звичайною функцією, що викликається з .bind(this)
є невеличка різниця:
.bind(this)
створює “зв’язану версію” функції.- Стрілка
=>
не створює жодних прив’язок. Ця функція просто не маєthis
. Пошукthis
здійснюється так само, як і звичайний пошук змінних: у зовнішньому лексичному середовищі.
Стрілкові функції не мають “arguments”
Стрілкові функції також не мають змінної arguments
.
Це чудово підходить для створення декораторів, коли нам потрібно прокинути виклик з поточними this
та arguments
.
Наприклад, defer(f, ms)
приймає функцію і повертає обгортку над нею, яка відкладає виклик на ms
мілісекунд:
function defer(f, ms) {
return function() {
setTimeout(() => f.apply(this, arguments), ms);
};
}
function sayHi(who) {
alert('Привіт, ' + who);
}
let sayHiDeferred = defer(sayHi, 2000);
sayHiDeferred("Іван"); // "Привіт, Іван" через 2 секунди
Те ж саме без стрілкової функції виглядатиме так:
function defer(f, ms) {
return function(...args) {
let ctx = this;
setTimeout(function() {
return f.apply(ctx, args);
}, ms);
};
}
Тут нам довелося створити додаткові змінні args
and ctx
, щоб функція всередині setTimeout
могла їх прийняти.
Підсумки
Стрілкові функції:
- Не мають
this
- Не мають
arguments
- Не можуть бути викликані з
new
- Також вони не мають
super
, але до цієї теми ми ще не дійшли. Ми про це поговоримо у розділі Наслідування класу
Це все тому, що вони призначені для невеличких фрагментів коду, які не мають власного “контексту”, а скоріше працюють у поточному. І вони дійсно дуже добре впорюються з цим завданням.