--- title: try...catch slug: Web/JavaScript/Reference/Statements/try...catch tags: - Error - JavaScript - виняток - помилка translation_of: Web/JavaScript/Reference/Statements/try...catch ---
{{jsSidebar("Statements")}}

Конструкція try...catch позначає блок команд, які треба виконати, та визначає реакцію в разі, якщо буде викинуто виняток.

{{EmbedInteractiveExample("pages/js/statement-trycatch.html")}}

Синтаксис

try {
  try_statements
}
[catch (exception_var_1 if condition_1) { // нестандартна форма
  catch_statements_1
}]
...
[catch (exception_var_2) {
  catch_statements_2
}]
[finally {
  finally_statements
}]
try_statements
Команди, які треба виконати.
catch_statements_1, catch_statements_2
Команди, що виконуються, якщо викинуто виняток у блоці try.
exception_var_1, exception_var_2
Ідентифікатор, що містить об'єкт винятку для відповідного блоку catch.
condition_1
Умовний вираз.
finally_statements
Команди, що виконуються після завершення блоку try. Ці команди виконуються незалежно від того, чи було викинуто або перехоплено виняток.

Опис

Вираз try містить одну або більше команд у блоці try. Фігурні дужки {} є обов'язковими, навіть для однієї команди. Має бути присутній принаймні один блок catch або finally. Це утворює три можливі форми виразу try:

  1. try...catch
  2. try...finally
  3. try...catch...finally

Блок catch містить команди, які визначають, що робити, якщо викинуто виняток у блоці try. Отже, ви хочете, щоб блок try виконався успішно, а в разі неуспіху ви хочете передати контроль до блоку catch. В разі, якщо будь-який вираз всередині блоку try (або функція, викликана зсередини блоку try) викидає виняток, контроль негайно переходить до блоку catch. Якщо жодних винятків у блоці try не було викинуто, блок catch пропускається.

Блок finally виконується після виконання блоків try та catch, але до команд, що йдуть після виразу try. Він завжди виконується, незалежно від того, чи було викинуто або перехоплено виняток.

Ви можете створити один або більше вкладених виразів try. Якщо внутрішній try не має блоку catch, контроль передається у блок catch зовнішнього try.

Ви також можете використовувати try, щоб обробляти винятки JavaScript. Ви знайдете більше інформації щодо винятків JavaScript у Посібнику JavaScript.

Безумовний catch

Коли використовується один безумовний блок catch, перехід у catch відбувається у випадку викидання будь-якого винятку. Наприклад, коли виняток стається у наступному коді, контроль передається до блоку catch.

try {
  throw 'myException'; // генерує виняток
}
catch (e) {
  // команди обробки будь-яких винятків
  logMyErrors(e); // передає об'єкт винятку до обробника помилок
}

Блок catch вказує ідентифікатор (e у наведеному прикладі), який містить значення, визначене у операторі throw. Блок catch унікальний тим, що JavaScript створює цей ідентифікатор при вході у блок catch, а також додає його у область видимості; ідентифікатор "живе" тільки протягом виконання блоку catch; коли catch завершується, ідентифікатор більше недоступний.

Умовний блок catch

{{non-standard_header}}

Ви також можете використати один або декілька умовних блоків catch для обробки специфічних винятків. В цьому випадку вхід у відповідний блок catch відбувається, коли викидається вказаний виняток. У наступному прикладі код у блоці try може викинути один з трьох винятків: {{jsxref("TypeError")}}, {{jsxref("RangeError")}} або {{jsxref("EvalError")}}. Коли виникає виняток, контроль передається до відповідного блоку catch. Якщо виняток не є одним із вказаних, і був знайдений безумовний блок catch, контроль передається до цього блоку catch.

Якщо ви використовуєте безумовний catch з одним або кількома умовними блоками catch, безумовний catch має бути вказаний останнім. Інакше безумовний catch перехоплюватиме всі види винятків до того, як вони потраплять в умовні блоки.

Нагадування: ця функціональність не є частиною специфікації ECMAScript і ніколи не прибиралася з Firefox 59. Вона більше не підтримується у жодних сучасних веб-переглядачах.

try {
  myroutine(); // може викинути три типи винятків
} catch (e if e instanceof TypeError) {
  // команди обробки винятків типу TypeError
} catch (e if e instanceof RangeError) {
  // команди обробки винятків типу RangeError
} catch (e if e instanceof EvalError) {
  // команди обробки винятків типу EvalError
} catch (e) {
  // команди обробки не вказаних типів винятків
  logMyErrors(e); // передати об'єкт винятку до обробника помилок
}

Ось такі ж "Умовні блоки catch", написані кодом, що відповідає специфікації ECMAScript (він доволі багатослівний, зате працює всюди):

try {
  myroutine(); // може викинути три типи винятків
} catch (e) {
  if (e instanceof TypeError) {
    // команди обробки винятків типу TypeError
  } else if (e instanceof RangeError) {
    // команди обробки винятків типу RangeError
  } else if (e instanceof EvalError) {
    // команди обробки винятків типу EvalError
  } else {
    // команди обробки не вказаних типів винятків
    logMyErrors(e); // передати об'єкт винятку до обробника помилок
  }
}

Ідентифікатор винятку

Коли викидається виняток у блоці try, ідентифікатор exception_var (наприклад, e у catch (e)) містить значення, вказане у виразі throw. Ви можете скористатись цим ідентифікатором, щоб отримати інформацію про виняток. Це локальний ідентифікатор блоку catch. Тобто, він створюється при вході у catch, а після того, як виконання блоку catch завершується, ідентифікатор більше недоступний.

function isValidJSON(text) {
  try {
    JSON.parse(text);
    return true;
  } catch {
    return false;
  }
}

Блок finally

Блок finally містить команди, які виконуються після виконання блоків try та catch, але до команд, що розташовані після конструкції  try...catch...finally. Зверніть увагу, що finally виконується незалежно від того, чи був викинутий виняток. Також, якщо виняток було викинуто, команди блоку finally виконуються навіть якщо немає блоку catch, щоб обробити виняток.

Ви можете скористатись блоком finally, щоб у разі викидання винятку ваш скрипт переривався красиво; наприклад, вам може знадобитися звільнити ресурс, до якого був прив'язаний ваш скрипт.

Це може виглядати дивним, мати спеціальний блок, пов'язаний з винятками, що виконується незалежно від того, чи стався виняток, але ця конструкція насправді виконує свою задачу. Важливим моментом є те, що блок finally виконується завжди, на відміну від звичайного коду, розташованого після try...catch.

Наприклад, якщо станеться інший виняток всередині catch цього try, будь-який код, що не був виконаний у зовнішньому try, що замикає цей try...catch (або у головному потоці, якщо виконувався не зовнішній try), не буде виконаний, оскільки контроль негайно перейде до блоку catch зовнішнього try (або до внутнішнього генератора помилок, якщо виконується не блок try).

Таким чином, будь який поточний код очистки, що виконується у цій зовнішній (або головній) секції перед закінченням, буде пропущений. Однак, якщо вираз try містить блок finally, то спочатку буде виконаний код блоку finally, дозволяючи зробити очистку, і тільки ПОТІМ контроль буде передано до блоку catch іншого try (або до генератора помилок) для обробки винятку.

Отже, якщо поточна очистка повинна бути зроблена, не зважаючи на те, чи успішно виконаний код у try...catch, тоді, якби блок finally виконувався тільки після винятку, той самий код очистки довелося б повторювати і всередині, і поза блоком finally, і, таким чином, немає причини не мати один лише блок finally, який виконується незалежно від того, стався виняток чи ні.

Наступний приклад відкриває файл і далі виконує команди, які використовують цей файл (JavaScript на стороні сервера дозволяє звертатись до файлів). Якщо викидається виняток, доки файл відкритий, блок finally закриває цей файл до того, як скрипт переривається. Код у блоці finally також виконується з явним поверненням з блоку try або catch.

openMyFile();
try {
  // прив'язати ресурс
  writeMyFile(theData);
}
finally {
  closeMyFile(); // завжди закривати ресурс
}

Приклади

Вкладені блоки try

Спочатку подивимось, що відбувається тут:

try {
  try {
    throw new Error('ой-ой');
  }
  finally {
    console.log('finally');
  }
}
catch (ex) {
  console.error('зовнішній', ex.message);
}

// Результат:
// "finally"
// "зовнішній" "ой-ой"

Тепер, якщо ми вже перехопили виняток у внутрішньому try, додавши блок catch.

try {
  try {
    throw new Error('ой-ой');
  }
  catch (ex) {
    console.error('внутрішній', ex.message);
  }
  finally {
    console.log('finally');
  }
}
catch (ex) {
  console.error('зовнішній', ex.message);
}

// Результат:
// "внутрішній" "ой-ой"
// "finally"

А тепер викинемо цю помилку повторно.

try {
  try {
    throw new Error('ой-ой');
  }
  catch (ex) {
    console.error('внутрішній', ex.message);
    throw ex;
  }
  finally {
    console.log('finally');
  }
}
catch (ex) {
  console.error('зовнішній', ex.message);
}

// Результат:
// "внутрішній" "ой-ой"
// "finally"
// "зовнішній" "ой-ой"

Будь-який виняток буде перехоплений лише один раз найближчим замикаючим блоком catch, якщо тільки він не був викинутий повторно.  Звісно, будь-які нові винятки, викинуті у "внутрішньому" блоці (бо код у блоці catch може зробити те, що викине помилку), будуть перехоплені "зовнішнім" блоком.

Повернення значень з блоку finally

Якщо блок finally повертає значення, це значення повертається усією конструкцією try-catch-finally, не зважаючи на будь-які інші оператори return у блоках try та catch. Це стосується й винятків, викинутих всередині блоку catch:

(function() {
  try {
    try {
      throw new Error('ой-ой');
    }
    catch (ex) {
      console.error('внутрішній', ex.message);
      throw ex;
    }
    finally {
      console.log('finally');
      return;
    }
  }
  catch (ex) {
    console.error('зовнішній', ex.message);
  }
})();

// Результат:
// "внутрішній" "ой-ой"
// "finally"

Зовнішній "ой-ой" не викидається через return у блоці finally. Те саме стосувалося б будь-якого значення, що поверталося б з блоку catch.

Специфікації

Специфікація Статус Коментар
{{SpecName('ES3')}} {{Spec2('ES3')}} Початкове визначення. Реалізоване у JavaScript 1.4
{{SpecName('ES5.1', '#sec-12.14', 'try statement')}} {{Spec2('ES5.1')}}
{{SpecName('ES6', '#sec-try-statement', 'try statement')}} {{Spec2('ES6')}}
{{SpecName('ESDraft', '#sec-try-statement', 'try statement')}} {{Spec2('ESDraft')}} Не є частиною нинішнього стандарту ECMA-262: Використання кількох блоків catch та умовні блоки (розширення SpiderMonkey, JavaScript 1.5).

Сумісність з веб-переглядачами

{{Compat("javascript.statements.try_catch")}}

Див. також