Jak działa instrukcja return w bloku try / catch?
function example() {
try {
return true;
}
finally {
return false;
}
}
Oczekuję, że dane wyjściowe tej funkcji będą true, ale zamiast tego jest false!
Odpowiedzi:
Wreszcie zawsze wykonuje. Do tego służy, co oznacza, że zwrot jest używany w twoim przypadku.
Będziesz chciał zmienić swój kod, aby wyglądał bardziej tak:
function example() {
var returnState = false; // initialisation value is really up to the design
try {
returnState = true;
}
catch {
returnState = false;
}
finally {
return returnState;
}
}
Ogólnie rzecz biorąc, nigdy nie chcesz mieć więcej niż jednej instrukcji return w funkcji, takie są przyczyny.
Według ECMA-262 (z dnia 5 grudnia 2009 r.), S. 96:
Produkcja
TryStatement : try Block Finallyjest oceniana w następujący sposób:
- Niech B będzie wynikiem oceny bloku.
- Niech F będzie wynikiem oceny Ostatecznie.
- Jeśli F.typ jest normalny, zwróć B.
- Powrót F.
A ze strony 36:
Rodzaj budowy służy do wyjaśnienia zachowań oświadczenia (
break,continue,returnithrow), które wykonują nielokalnych transfery kontroli. Wartości rodzaju budowy są trójki postaci (typ, wartości docelowej) , gdzie rodzaj jest jednym znormal,break,continue,return, athrow, wartość jest dowolna wartość język ECMAScript lub pusty i cel jest każdy identyfikator ECMAScript lub pusty.
To jasne, że return falsebyłoby ustawić typ zakończenia wreszcie jako zwrot , które powodują try ... finallyzrobić 4. Zwrot F .
Ostateczne przepisywanie bloku spróbuj powrotu bloku (mówiąc w przenośni).
Chciałem tylko zaznaczyć, że jeśli w końcu coś zwrócisz, to zostanie to zwrócone z funkcji. Ale jeśli w końcu nie ma słowa 'return' - zostanie zwrócona wartość z bloku try;
function example() {
try {
return true;
}
finally {
console.log('finally')
}
}
console.log(example());
// -> finally
// -> true
Zatem return-w końcu- przepisuje zwrot z -try- return.
dlaczego otrzymujesz fałsz, czy wróciłeś w ostatnim bloku. ostatecznie blok powinien być wykonywany zawsze. więc twoje return truezmiany wreturn false
function example() {
try {
return true;
}
catch {
return false;
}
}
O ile wiem, finallyblok zawsze jest wykonywany, niezależnie od tego, czy w returnśrodku znajduje się instrukcja, tryczy nie. Ergo, otrzymujesz wartość zwróconą przez returninstrukcję wewnątrz końcowego bloku.
Przetestowałem to w Firefoksie 3.6.10 i Chrome 6.0.472.63 w Ubuntu. Możliwe, że ten kod może zachowywać się inaczej w innych przeglądarkach.
Wracając z ostatecznego bloku
Jeśli
finally-block zwraca wartość, ta wartość staje się wartością zwracaną całejtry-catch-finallyinstrukcji, niezależnie od jakichkolwiekreturninstrukcji wtryicatch-blocks
Źródła: developer.mozilla.org
Podam tutaj nieco inną odpowiedź: Tak, zarówno blok , jak tryi finallysą wykonywane i finallymają pierwszeństwo przed rzeczywistą wartością „zwracaną” funkcji. Jednak te wartości zwracane nie zawsze są używane w kodzie.
Dlatego:
res.send()z Express.js, który tworzy odpowiedź HTTP i wysyła ją.tryi finallyblok wykonają tę funkcję w następujący sposób:try {
// Get DB records etc.
return res.send('try');
} catch(e) {
// log errors
} finally {
return res.send('finally');
}
Ten kod pokaże ciąg tryw Twojej przeglądarce. TAKŻE przykład pokaże błąd w twojej konsoli. res.send()Funkcja jest wywoływana dwukrotnie . Stanie się tak w przypadku wszystkiego, co jest funkcją. Blokada try-catch-last zaciemni ten fakt niewprawnym okiem, ponieważ (osobiście) kojarzę tylkoreturn wartości z zakresami funkcji.
Imho najlepiej jest nigdy nie używać returnwewnątrz finallybloku . Zbyt mocno skomplikuje Twój kod i potencjalnie maskuje błędy.
W rzeczywistości istnieje domyślna reguła inspekcji kodu ustawiona w PHPStorm, która daje „Ostrzeżenie” w tym przypadku:
https://www.jetbrains.com/help/phpstorm/javascript-and-typescript-return-inside-finally-block.html
finally ?użyłbym finally tylko do porządkowania rzeczy. Wszystko, co nie jest krytyczne dla wartości zwracanej przez funkcję.
Może to mieć sens, jeśli się nad tym zastanowisz, ponieważ gdy polegasz na wierszu kodu poniżej finally, zakładasz, że mogą wystąpić błędy w trylub catch. Ale te ostatnie 2 są faktycznymi elementami składowymi obsługi błędów. Po prostu użyj returnin tryi catchzamiast.
A co z tym?
doubleReturn();
function doubleReturn() {
let sex = 'boy';
try {
return sex;
console.log('this never gets called...');
} catch (e) {} finally {
sex = 'girl';
alert(sex);
}
}