Як працює оператор return у блоці try / catch?
function example() {
try {
return true;
}
finally {
return false;
}
}
Я очікую, що результат цієї функції буде true
, але натомість він є false
!
Відповіді:
Нарешті завжди виконує. Ось для чого він призначений, а це означає, що у вашому випадку використовується повернення.
Ви захочете змінити свій код, щоб він був приблизно таким:
function example() {
var returnState = false; // initialisation value is really up to the design
try {
returnState = true;
}
catch {
returnState = false;
}
finally {
return returnState;
}
}
Взагалі кажучи, ви ніколи не хочете, щоб у функції було більше одного оператора return, подібні речі - ось чому.
Відповідно до ECMA-262 (5ed, грудень 2009 р.), В с. 96:
Виробництво
TryStatement : try Block Finally
оцінюється наступним чином:
- Нехай B є результатом оцінки Block.
- Нехай F є результатом оцінки Нарешті.
- Якщо тип F. нормальний, поверніть B.
- Повернення Ф.
І зі стор. 36:
Тип Завершення використовується для пояснення поведінки операторів (
break
,continue
,return
іthrow
) , які виконують нелокальних передачу управління. Значення типу завершення є триплети виду (тип, значення, мета) , де тип є одним зnormal
,break
,continue
,return
, абоthrow
, значення будь-яке значення ECMAScript мови або порожній, і цільової будь ідентифікатор ECMAScript або порожній.
Очевидно , що return false
б встановити тип завершення в кінці кінців , як повернення , що викликає try ... finally
робити 4. Повернення F .
чому ви отримуєте false - це повернення в остаточному блоці. нарешті блок повинен виконуватися завжди. так що ваші return true
зміни доreturn false
function example() {
try {
return true;
}
catch {
return false;
}
}
Нарешті блок переписує спробу повернення блоку (образно кажучи).
Просто хотів зазначити, що якщо ви повернете щось із, нарешті, це буде повернуто з функції. Але якщо нарешті немає слова "return" - йому буде повернуто значення з блоку try;
function example() {
try {
return true;
}
finally {
console.log('finally')
}
}
console.log(example());
// -> finally
// -> true
Отже-нарешті- return
переписує повернення -спробо- return
.
Наскільки мені відомо, finally
блок завжди виконується, незалежно від того, є у вас return
заява всередині try
чи ні. Ерго, ви отримуєте значення, яке повертається return
оператором всередині блоку нарешті.
Я протестував це за допомогою Firefox 3.6.10 та Chrome 6.0.472.63, обидва в Ubuntu. Можливо, цей код може поводитися по-різному в інших браузерах.
Тут я дам трохи іншу відповідь: так, try
і finally
блок, і блок виконуються, і finally
має перевагу над фактичним значенням "return" для функції. Однак ці повернені значення не завжди використовуються у вашому коді.
Ось чому:
res.send()
Express.js, який створює відповідь HTTP і відправляє її.try
і finally
блок будуть виконувати цю функцію так:try {
// Get DB records etc.
return res.send('try');
} catch(e) {
// log errors
} finally {
return res.send('finally');
}
Цей код покаже рядок try
у вашому браузері. ТАКОЖ, приклад покаже помилку у вашій консолі. res.send()
Функція викликається двічі . Це відбуватиметься з усім, що є функцією. Блок try-catch-нарешті затуманить цей факт для нетренованого ока, оскільки (особисто) я пов'язую лише return
значення з сферами функцій.
Імхо, ваша найкраща ставка - ніколи не використовувати return
всередині finally
блоку . Це призведе до ускладнення вашого коду та потенційно замаскує помилки.
Насправді у PHPStorm встановлено правило перевірки коду за замовчуванням, яке дає "Попередження" про це:
https://www.jetbrains.com/help/phpstorm/javascript-and-typescript-return-inside-finally-block.html
finally
?Я б використовував finally
лише для прибирання речей. Все, що не є критичним для поверненого значення функції.
Це може мати сенс, якщо ви задумаєтесь, тому що коли ви залежате від рядка коду finally
, ви припускаєте, що в try
або можуть бути помилки catch
. Але ці останні 2 - це фактичні будівельні блоки обробки помилок. Просто використовуйте return
in try
і catch
замість цього.
Повернення з блоку нарешті
Якщо
finally
-block повертає значення, це значення стає повертаним значенням усьогоtry-catch-finally
оператора, незалежно від будь-якихreturn
операторів уtry
таcatch
-blocks
Довідково: developer.mozilla.org
Як що до цього?
doubleReturn();
function doubleReturn() {
let sex = 'boy';
try {
return sex;
console.log('this never gets called...');
} catch (e) {} finally {
sex = 'girl';
alert(sex);
}
}