Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Що відбувається, коли виникає помилка». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Рушій виявляє проблему, створює об'єкт `Error` з полями `name`, `message` і `stack`, викидає його через `throw` і піднімається стеком викликів у пошуках найближчого `try...catch`.** Якщо обробника немає, помилка «спливає» до самого верху і виконання коду припиняється; якщо обробник знайдено, робота продовжується після блоку `catch`. ```javascript try { console.log(a); // ReferenceError } catch (err) { console.log("Помилку спіймано:", err.message); } finally { console.log("Цей блок виконається завжди"); } ``` **Ключове:** помилка завжди рухається знизу вгору стеком викликів, і блок `finally` виконується в будь-якому разі, спіймали помилку чи ні.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**Коли в коді виникає помилка, рушій створює об'єкт `Error`, викидає його через `throw` і піднімається стеком викликів, шукаючи найближчий `try...catch`.** Якщо обробника не знайдено, виконання скрипта припиняється; якщо знайдено, програма продовжує роботу з рядка після блоку `catch`. ## Теорія ### TL;DR - Рушій (наприклад, V8 у Chrome та Node.js) натрапляє на ситуацію, яку не може обробити. - Автоматично створюється об'єкт помилки з `name`, `message` і `stack`. - Помилка викидається (`throw`) і піднімається вгору стеком викликів. - Рушій шукає найближчий `try...catch`; якщо в поточній функції його немає, пошук триває у функції-викликачі. - Без обробника помилка спливає до самого верху і виконання коду припиняється. - Зі спійманою помилкою програма продовжує роботу після блоку `catch`, а `finally` виконується в будь-якому випадку. ### Швидкий приклад ```javascript function test() { console.log(a); // ReferenceError } try { test(); } catch (err) { console.log("Помилку спіймано:", err.message); } ``` Тут помилка не призведе до падіння програми, бо її перехопив `catch`. ### Крок 1: рушій виявляє проблему Під час виконання коду рушій JavaScript натрапляє на ситуацію, яку не може обробити, наприклад: ```javascript console.log(a); ``` Змінна `a` не визначена. Рушій «бачить» це і створює об'єкт помилки: ```javascript ReferenceError: a is not defined ``` ### Крок 2: створюється об'єкт Error JavaScript автоматично створює об'єкт з інформацією про помилку: ```javascript { name: "ReferenceError", message: "a is not defined", stack: "Stack trace..." } ``` Він містить: - `name`, тип помилки; - `message`, текстовий опис; - `stack`, стек викликів, тобто де саме сталася помилка. ### Крок 3: помилка викидається і шукає обробник Після створення рушій «кидає» (throw) цю помилку вгору стеком викликів, тобто JavaScript шукає найближчий `try...catch`, який зможе її перехопити. Якщо помилка виникає всередині блоку `try`, JavaScript одразу переходить до відповідного `catch`. Якщо всередині поточної функції `try...catch` немає, рушій піднімається вгору стеком викликів, до функції, яка викликала поточну, і так далі, доки не знайде обробник. Якщо обробник не знайдено, помилка «спливає» до самого верху і виконання коду припиняється. ### Крок 4: припинення виконання, якщо помилку не спіймано Якщо помилку не спіймано, програма зупиняється: ```javascript console.log(a); console.log("Цей код не виконається"); ``` Після `ReferenceError` у першому рядку виконання переривається, і другий рядок уже не буде виконано. ### Крок 5: відновлення роботи і блок finally Якщо помилку спіймано в `try...catch`, виконання програми продовжується після блоку `catch`: ```javascript try { JSON.parse("{ not valid json }"); } catch (error) { console.log("Сталася помилка:", error.message); } console.log("Код продовжується..."); ``` Вивід: ```javascript Сталася помилка: Expected property name or '}' in JSON at position 2 Код продовжується... ``` Якщо додати блок `finally`, він виконається завжди, незалежно від того, була помилка чи ні: ```javascript try { throw new Error("Помилка!"); } catch (e) { console.log("Спіймали помилку"); } finally { console.log("Цей блок виконається в будь-якому разі"); } ``` Саме тому `finally` використовують для прибирання: закрити з'єднання, зняти індикатор завантаження, звільнити ресурс. ### Етапи одним поглядом | Етап | Що відбувається | | --- | --- | | 1 | Виявлення проблеми | | 2 | Створення об'єкта помилки | | 3 | Викидання (`throw`) помилки | | 4 | Пошук обробника (`try...catch`) | | 5 | Переривання виконання, якщо помилку не спіймано | | 6 | Продовження роботи, якщо помилку оброблено | | 7 | Виконання блоку `finally`, якщо він є | ### Типові помилки - **Думати, що після `catch` виконання повертається у місце збою.** Ні, рядки в `try` після проблемного вже пропущені назавжди; програма продовжується з коду після всієї конструкції. - **Очікувати, що `try...catch` спіймає асинхронну помилку.** Виняток усередині `setTimeout` або в необробленому промісі виникає в іншому такті event loop, коли зовнішній `try` уже завершився. - **Ігнорувати `stack`.** Саме стек викликів показує ланцюжок функцій, який привів до збою; логувати лише `message` означає викидати найкорисніше. - **Ставити `return` у `finally`.** Таке значення перекриє і результат `try`, і викинуту помилку, тому збій просто зникне без сліду. - **Вважати, що неспіймана помилка ламає лише один рядок.** Вона зупиняє весь поточний стек викликів, тому далі не виконається нічого з цієї гілки коду.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.