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 Finally
jest 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
,return
ithrow
), 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 false
byłoby ustawić typ zakończenia wreszcie jako zwrot , które powodują try ... finally
zrobić 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 true
zmiany wreturn false
function example() {
try {
return true;
}
catch {
return false;
}
}
O ile wiem, finally
blok zawsze jest wykonywany, niezależnie od tego, czy w return
środku znajduje się instrukcja, try
czy nie. Ergo, otrzymujesz wartość zwróconą przez return
instrukcję 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-finally
instrukcji, niezależnie od jakichkolwiekreturn
instrukcji wtry
icatch
-blocks
Źródła: developer.mozilla.org
Podam tutaj nieco inną odpowiedź: Tak, zarówno blok , jak try
i finally
są wykonywane i finally
mają 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ą.try
i finally
blok 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 try
w 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ć return
wewnątrz finally
bloku . 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 try
lub catch
. Ale te ostatnie 2 są faktycznymi elementami składowymi obsługi błędów. Po prostu użyj return
in try
i catch
zamiast.
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);
}
}