Як працює оператор 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 - це фактичні будівельні блоки обробки помилок. Просто використовуйте returnin 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);
}
}