Відмінності між стрілковою функцією, оголошенням функції та виразом функції
В JavaScript є кілька способів оголошення функцій: Function Declaration, Function Expression та Arrow Function. Кожен з них має свої особливості щодо hoisting, використання this, можливості бути конструктором і нюанси в синтаксисі та застосуванні.
Коротка таблиця порівняння
| Характеристика | Function Declaration | Function Expression | Arrow Function |
|---|---|---|---|
| Синтаксис | function name() { ... } | const name = function() { ... } | const name = () => { ... } |
| Hoisting | Повний (функція доступна до оголошення) | Частковий (змінна піднімається, але функція ініціалізується лише в точці оголошення) | Ні (коли оголошена з const/let, функція не піднімається) |
Власний this | Так (залежить від виклику) | Так (залежить від виклику) | Ні (лексичний this, успадкований з зовнішньої області) |
arguments | Доступний | Доступний | Ні (використовуйте ...rest) |
Використання з new | Так (може діяти як конструктор) | Так (якщо оголошена як звичайна функція) | Ні (Arrow Function не може бути конструктором) |
| Застосування | Загальні функції, конструктори | Замикання, колбеки | Однорядкові функції, колбеки |
Деталі та приклади
Hoisting
- Function Declaration повністю піднімається. Це означає, що ми можемо викликати таку функцію навіть до її фактичного оголошення у файлі.
javascript
hello(); // "Hello from Declaration!"
function hello() {
console.log("Hello from Declaration!");
}- Function Expression з
varпіднімається як змінна (стає undefined до ініціалізації), але сама функція стає доступною лише після рядка присвоєння. Якщо використовувати const або let, немає підняття для функції як готового значення — ви не можете викликати функцію до її оголошення.
javascript
// Приклад з var
console.log(typeof sayHi); // "undefined"
// sayHi(); // Помилка: sayHi is not a function
var sayHi = function () {
console.log("Hello from Expression!");
};- Arrow Function зазвичай оголошується з
constабоlet, тому не піднімається як готова функція. Якщо спробувати викликати стрілкову функцію до оголошення, отримаєте помилку.
javascript
// greet(); // Помилка: greet is not defined
const greet = () => console.log("Hello from Arrow!");Контекст this
- Function Declaration та Function Expression (якщо не стрілкові) мають контекст
this, що визначається методом виклику (або .call, .apply, .bind). - Arrow Function не має власного
this: він лексично запозичується з області, де оголошена стрілкова функція.
javascript
const user = {
name: "Alice",
sayHello: function() {
console.log("Hello, I'm " + this.name);
},
arrowHello: () => {
console.log("Hello, I'm " + this.name);
}
};
user.sayHello(); // "Hello, I'm Alice" - this = user
user.arrowHello(); // "Hello, I'm undefined" - this взято з зовнішньої області (глобальна / undefined)arguments та оператор ...rest
- Function Declaration та Function Expression мають псевдомасив
arguments, що містить усі аргументи функції. - Arrow Function не має
arguments, але ви можете використовувати оператор...rest, щоб отримати всі аргументи.
javascript
function sumAll() {
let total = 0;
for (const arg of arguments) {
total += arg;
}
return total;
}
const sumAllArrow = (...args) => {
return args.reduce((acc, curr) => acc + curr, 0);
};Використання з new
- Тільки Function Declaration та Function Expression (не в стрілковому форматі) можуть бути конструкторами.
- Arrow Function не може бути використана з
new, оскільки не має внутрішнього механізму[[Construct]].
Коротка відповідь
Для співбесідиPremium
Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.