Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Різниця між function declaration і function expression». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Function declaration (`function greet() {}`) піднімається (hoisting) цілком, тому функцію можна викликати ще до рядка з оголошенням; function expression (`const greet = function () {}`) створюється тільки в момент виконання присвоєння, тому до цього рядка виклик падає з помилкою.** Declaration завжди іменована і потрапляє в область видимості на етапі її ініціалізації, а expression є частиною виразу, може бути анонімною або іменованою, і зручна для колбеків та обробників подій. ```javascript greet(); // працює: declaration піднято повністю function greet() { console.log('Hello!'); } bye(); // ReferenceError: Cannot access 'bye' before initialization const bye = function () { console.log('Bye!'); }; ``` **Ключове:** declaration створюється заздалегідь, при ініціалізації scope, а expression, у момент виконання рядка з присвоєнням.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**Function declaration оголошує функцію заздалегідь, тому вона доступна в усій своїй області видимості, навіть вище рядка оголошення, а function expression створює функцію лише тоді, коли виконається рядок із присвоєнням.** В обох випадках виходить звичайна функція, різниця тільки в тому, у який момент вона з'являється у scope і чи обов'язково має ім'я. ## Теорія ### TL;DR - `function greet() {}` це declaration: піднімається (hoisting) разом із тілом, викликати можна в будь-якому місці свого scope. - `const greet = function () {}` це expression: піднімається лише змінна, сама функція з'являється після присвоєння. - Виклик expression до присвоєння дає `ReferenceError` для `const` і `let` (temporal dead zone) або `TypeError: greet is not a function` для `var`. - Declaration завжди іменована, expression може бути анонімною або іменованою. - Declaration беруть для основних функцій модуля, expression і arrow function, для колбеків, обробників та частин виразів. ### Швидкий приклад ```javascript // --- Function Declaration --- sayHi(); // працює function sayHi() { console.log('Hi!'); } // --- Function Expression --- sayBye(); // помилка: змінна ще не ініціалізована const sayBye = function () { console.log('Bye!'); }; ``` ### Function declaration Оголошення функції записується ключовим словом `function` на початку інструкції: ```javascript function sayHello() { console.log('Hello!'); } ``` Особливості: - **Hoisting.** Функція доступна до місця свого оголошення: рушій створює її ще на етапі ініціалізації області видимості, разом із тілом. - Ім'я функції фіксоване і доступне в поточній області видимості. - Викликати можна в будь-якому місці файлу чи блоку, навіть вище коду оголошення. ```javascript greet(); // працює, хоча функція оголошена нижче function greet() { console.log('Hello!'); } ``` Результат: ```javascript Hello! ``` ### Function expression Функціональний вираз, це функція в правій частині виразу, найчастіше присвоєння: ```javascript const sayHello = function () { console.log('Hello!'); }; ``` або стрілкова версія: ```javascript const sayHello = () => console.log('Hello!'); ``` Особливості: - **Не піднімається як оголошення.** Змінна створюється, але функція в ній недоступна до ініціалізації. - Може бути **анонімною** (без імені) або **іменованою** (`const f = function inner() {}`, ім'я `inner` видно тільки всередині самої функції і зручне у стеку викликів). - Це вираз, тому викликати функцію можна **тільки після** присвоєння. ```javascript sayHello(); // помилка: до присвоєння функції ще немає const sayHello = function () { console.log('Hello!'); }; ``` ### Ключові відмінності | Властивість | Function Declaration | Function Expression | | --- | --- | --- | | **Hoisting (підняття)** | Так, доступна до оголошення | Ні, недоступна до присвоєння | | **Коли створюється** | При ініціалізації області видимості | Під час виконання рядка | | **Чи можна викликати до оголошення?** | Так | Ні | | **Ім'я функції** | Обов'язкове, декларація завжди іменована | Може бути анонімною або іменованою | | **Підходить для** | Основних функцій, потрібних усюди | Локальних, переданих як аргумент, колбеків | | **Приклад використання** | `function sum(a, b) {}` | `const sum = (a, b) => {}` | ### Що обирати - **Function declaration**, коли функція потрібна широко в модулі і її зручно викликати в будь-якому місці, наприклад допоміжні функції верхнього рівня. - **Function expression або arrow function**, коли функція потрібна локально: як обробник події, колбек, аргумент `map`/`filter`, частина виразу або значення, яке повертають з іншої функції. Коротко запам'ятати: > `function declaration` створюється заздалегідь (hoisting). > `function expression` створюється в момент виконання. ### Типові помилки - **Думати, що expression теж піднімається.** Піднімається лише оголошення змінної. З `var` вона дорівнює `undefined`, тому виклик дає `TypeError: sayBye is not a function`; з `const` і `let` змінна перебуває в temporal dead zone, тому виклик дає `ReferenceError: Cannot access 'sayBye' before initialization`. - **Покладатися на hoisting declaration усередині блоку.** У строгому режимі оголошення функції всередині `if` або циклу обмежене блоком, і поза цим блоком функції не існує. - **Робити колбеки анонімними без потреби.** Іменований вираз (`const handler = function handler() {}`) дає осмислений стек викликів під час налагодження. - **Плутати arrow function з експресією `function`.** Arrow function теж є виразом, але не має власного `this`, `arguments` і не може бути конструктором. - **Оголошувати одну й ту саму declaration двічі.** Пізніше оголошення мовчки перекриває попереднє, і помилка виявиться лише під час виконання.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.