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

Синтаксис

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
This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. There may also be large incompatibilities between implementations and the behavior may change in the future.

Ви також можете використати один або декілька умовних блоків catch для обробки специфічних винятків. В цьому випадку вхід у відповідний блок catch відбувається, коли викидається вказаний виняток. У наступному прикладі код у блоці try може викинути один з трьох винятків: TypeError, RangeError або 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.

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

Специфікація Статус Коментар
ECMAScript 3rd Edition (ECMA-262) Standard Початкове визначення. Реалізоване у JavaScript 1.4
ECMAScript 5.1 (ECMA-262)
The definition of 'try statement' in that specification.
Standard
ECMAScript 2015 (6th Edition, ECMA-262)
The definition of 'try statement' in that specification.
Standard
ECMAScript Latest Draft (ECMA-262)
The definition of 'try statement' in that specification.
Draft Не є частиною нинішнього стандарту ECMA-262: Використання кількох блоків catch та умовні блоки (розширення SpiderMonkey, JavaScript 1.5).

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

Update compatibility data on GitHub
DesktopMobileServer
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome for AndroidFirefox for AndroidOpera for AndroidSafari on iOSSamsung InternetNode.js
try...catchChrome Full support YesEdge Full support YesFirefox Full support 1IE Full support 6Opera Full support YesSafari Full support YesWebView Android Full support YesChrome Android Full support YesFirefox Android Full support 4Opera Android Full support YesSafari iOS Full support YesSamsung Internet Android Full support Yesnodejs Full support Yes
Conditional clauses
DeprecatedNon-standard
Chrome No support NoEdge No support NoFirefox No support 1 — 59IE No support NoOpera No support NoSafari No support NoWebView Android No support NoChrome Android No support NoFirefox Android No support 4 — 59Opera Android No support NoSafari iOS No support NoSamsung Internet Android No support Nonodejs No support No
Optional catch bindingChrome Full support 66Edge No support NoFirefox Full support 58IE No support NoOpera Full support 53Safari Full support 11.1WebView Android Full support 66Chrome Android Full support 66Firefox Android Full support 58Opera Android Full support 47Safari iOS Full support 11.3Samsung Internet Android No support Nonodejs Full support 10.0.0

Legend

Full support  
Full support
No support  
No support
Non-standard. Expect poor cross-browser support.
Non-standard. Expect poor cross-browser support.
Deprecated. Not for use in new websites.
Deprecated. Not for use in new websites.

Див. також

Мітки документа й учасники

Зробили внесок у цю сторінку: DariaManko
Востаннє оновлена: DariaManko,