JavaScript · Синтаксис · Проміжний
Стрілочні функції та this
Опануй синтаксис стрілочних функцій та зрозумій як `this` поводиться по-різному у стрілочних і звичайних функціях — ключова відмінність для класів, зворотних викликів та обробників подій.
Короткий вступ до теми та пояснення перед вправами (вправи нижче):
Стрілочні функції у методах масиву, класах та промісах
#Стрілочні vs звичайні функції — довідник
#Вправи:
Переписати як стрілочну функцію
#Перепиши функцію `greet` як стрілочну функцію, присвоєну до `const`. Поведінка має бути ідентичною.
function greet(name) {
return "Hello, " + name + "!";
}
console.log(greet("Alice"));
Рішення
const greet = name => "Hello, " + name + "!";
console.log(greet("Alice"));
Неявне повернення — скоротити до одного рядка
#Скороти `multiply` до однорядкової стрілочної функції з неявним поверненням.
const multiply = (a, b) => {
return a * b;
};
console.log(multiply(3, 4));
Рішення
const multiply = (a, b) => a * b;
console.log(multiply(3, 4));
this у методі об'єкта — чому стрілка ламає
#Метод `describe` використовує стрілочну функцію і повертає неправильний результат. Виправ його так щоб `this` правильно посилався на об'єкт.
const user = {
name: "Alice",
age: 30,
describe: () => {
return `${this.name} is ${this.age} years old`;
}
};
console.log(user.describe());
Рішення
const user = {
name: "Alice",
age: 30,
describe() {
return `${this.name} is ${this.age} years old`;
}
};
console.log(user.describe());
Виправити this у setTimeout колбеку
#Клас `DelayedGreeter` має вивести привітання через 0мс, але `this.name` є undefined. Виправ за допомогою стрілочної функції.
class DelayedGreeter {
constructor(name) {
this.name = name;
}
greet() {
setTimeout(function() {
console.log("Hello, " + this.name + "!");
}, 0);
}
}
new DelayedGreeter("Alice").greet();
Рішення
class DelayedGreeter {
constructor(name) {
this.name = name;
}
greet() {
setTimeout(() => {
console.log("Hello, " + this.name + "!");
}, 0);
}
}
new DelayedGreeter("Alice").greet();
Стрілочні функції у map та filter
#З масиву `products` відфільтруй лише товари з `price > 100` і перетвори кожен лише на `name`. Використовуй стрілочні функції для обох операцій. Виведи результат.
const products = [
{ name: "Laptop", price: 999 },
{ name: "Mouse", price: 25 },
{ name: "Monitor", price: 399 },
{ name: "Keyboard", price: 75 },
];
// твій код тут
Рішення
const products = [
{ name: "Laptop", price: 999 },
{ name: "Mouse", price: 25 },
{ name: "Monitor", price: 399 },
{ name: "Keyboard", price: 75 },
];
const result = products
.filter(p => p.price > 100)
.map(p => p.name);
console.log(result);
Повернути об'єкт зі стрілочної функції
#Напиши стрілочну функцію `makeProduct`, яка приймає `name` і `price` та повертає об'єкт `{ name, price }` з неявним поверненням. Перевір з `"Laptop"` і `999`.
// твій код тут
console.log(makeProduct("Laptop", 999));
Рішення
const makeProduct = (name, price) => ({ name, price });
console.log(makeProduct("Laptop", 999));
Метод класу vs стрілочна властивість
#Клас `Counter` має `increment` як звичайний метод і `decrement` як стрілочну функцію-властивість. Виклич обидва на екземплярі та виведи `count` після кожного. Спостерігай яка форма коректно працює після деструктуризації.
class Counter {
count = 0;
increment() {
this.count++;
}
decrement = () => {
this.count--;
};
}
const c = new Counter();
c.increment();
console.log(c.count);
c.decrement();
console.log(c.count);
// Деструктуруй і виклич — яка ламається?
const { increment, decrement } = c;
increment();
console.log(c.count);
decrement();
console.log(c.count);
Рішення
class Counter {
count = 0;
increment() {
this.count++;
}
decrement = () => {
this.count--;
};
}
const c = new Counter();
c.increment();
console.log(c.count);
c.decrement();
console.log(c.count);
const { increment, decrement } = c;
try { increment(); } catch(e) { console.log("increment failed:", e.message); }
console.log(c.count);
decrement();
console.log(c.count);
Карінг через вкладені стрілочні функції
#Напиши каррованою функцію `add` зі стрілочними функціями: `add(a)(b)` має повертати `a + b`. Перевір через `add(3)(4)` та `add(10)(20)`.
// твій код тут console.log(add(3)(4)); console.log(add(10)(20));
Рішення
const add = a => b => a + b;
console.log(add(3)(4));
console.log(add(10)(20));
Стрілочні функції у ланцюжку промісів
#Завершити ланцюжок промісів: resolve з значенням `42`, потім подвоїти у `.then`, потім вивести результат у наступному `.then`. Використовуй стрілочні функції для обох колбеків.
const p = new Promise(resolve => {
resolve(42);
});
p
.then(/* подвоїти значення */)
.then(/* вивести результат */);
Рішення
const p = new Promise(resolve => {
resolve(42);
});
p
.then(val => val * 2)
.then(val => console.log(val));
Обрати правильний тип функції
#Код нижче має два баги: один метод неправильно використовує стрілочну функцію, а один колбек неправильно використовує звичайну функцію. Виправ обидва.
class Playlist {
constructor(name) {
this.name = name;
this.songs = [];
}
// Має виводити "Playlist: Rock"
describe: () => {
console.log("Playlist: " + this.name);
}
// Має виводити кожну пісню з назвою плейлиста
printSongs() {
this.songs.forEach(function(song) {
console.log(this.name + ": " + song);
});
}
}
const pl = new Playlist("Rock");
pl.songs = ["AC/DC", "Led Zeppelin"];
pl.describe();
pl.printSongs();
Рішення
class Playlist {
constructor(name) {
this.name = name;
this.songs = [];
}
describe() {
console.log("Playlist: " + this.name);
}
printSongs() {
this.songs.forEach(song => {
console.log(this.name + ": " + song);
});
}
}
const pl = new Playlist("Rock");
pl.songs = ["AC/DC", "Led Zeppelin"];
pl.describe();
pl.printSongs();