Как работает оператор return внутри блока try / catch?
function example() {
try {
return true;
}
finally {
return false;
}
}
Я ожидаю, что результат этой функции будет true, но вместо этого он есть false!
Ответы:
Наконец, всегда выполняется. Это то, для чего он нужен, а это значит, что в вашем случае используется return.
Вы захотите изменить свой код, чтобы он выглядел примерно так:
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 будет результатом вычисления finally.
- Если F.type нормальный, верните B.
- Возврат F.
И со стр.36:
Тип Завершение используется для объяснения поведения операторов (
break,continue,returnиthrow) , которые выполняют нелокальные передачу управления. Значения типа завершения являются триплеты вида (тип, значение, цель) , где тип является одним изnormal,break,continue,return, илиthrow, значение любое значение ECMAScript языка или пустой, и целевой любой идентификатор ECMAScript или пуст.
Очевидно , что return falseбы установить тип завершения в конце концов , как возвращение , что вызывает try ... finallyделать 4. Возвращение F .
Перезапись блока finally пытается вернуть блок (образно говоря).
Просто хотел указать, что если вы вернете что-то из finally, то оно будет возвращено из функции. Но если в finally нет слова return - будет возвращено значение из блока try;
function example() {
try {
return true;
}
finally {
console.log('finally')
}
}
console.log(example());
// -> finally
// -> true
Итак, -finally- returnперезаписывает возврат -try- return.
Насколько мне известно, finallyблок выполняется всегда , независимо от того, есть ли у вас returnвнутри оператор tryили нет. Итак, вы получаете значение, возвращаемое returnоператором внутри блока finally.
Я тестировал это с Firefox 3.6.10 и Chrome 6.0.472.63 как в Ubuntu. Возможно, что этот код может вести себя иначе в других браузерах.
Возвращение из блока finally
Если
finally-block возвращает значение, это значение становится возвращаемым значением всегоtry-catch-finallyоператора, независимо от любыхreturnоператоров вtryиcatch-blocks
Ссылка: developer.mozilla.org
Я дам здесь немного другой ответ: да, оба блока tryи finallyвыполняются и finallyимеют приоритет над фактическим "возвращаемым" значением для функции. Однако эти возвращаемые значения не всегда используются в вашем коде.
Вот почему:
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-finally скрывает этот факт от неподготовленного глаза, потому что (лично) я связываю 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.
Как насчет этого?
doubleReturn();
function doubleReturn() {
let sex = 'boy';
try {
return sex;
console.log('this never gets called...');
} catch (e) {} finally {
sex = 'girl';
alert(sex);
}
}