Почему блоки JavaScript try / finally заставляют функцию возвращаться дважды? - PullRequest
1 голос
/ 09 мая 2019

Блок finally всегда выполняет last, а оператор return возвращает управление туда, откуда был сделан вызов функции. При использовании вместе изнутри блока try / finally функция кажется возвращаемой дважды, а не один раз, при использовании внутри блока if-else возвращаемое значение блока finally вступает в силу. Один и тот же вызов метода возвращается дважды?

function print(value) {
    console.log(value);
    return value;
}

function testWrapped() {
    try {
        return print(true);
    } finally {
        return print(false);
    }
}

function test() {
    try {
        return true;
    } finally {
        return false;
    }
}


console.log("Result with wrapped value");
testWrapped();


console.log("Result when used inside an if statement:");
if (test()) {
    console.log("true");
} else {
    console.log("false");
}

приведенный выше код выдает следующий вывод:

Result with wrapped value
true
false
Result when used inside an if statement:
false

Ответы [ 3 ]

4 голосов
/ 09 мая 2019

Это потому, что вы используете finally, а не catch

Наконец, выполнится после попытки или перехвата.

В условном блоке он вернет последний оцененный элемент, false и выполните свой блок else.

см .: https://www.w3schools.com/jsref/jsref_try_catch.asp

Оператор try позволяет определить блок кода, который будет проверяться на наличие ошибок, пока онвыполняется.

Оператор catch позволяет определить блок кода, который будет выполнен, если в блоке try возникнет ошибка.

Оператор finally позволяет выполнить код после попытки ипоймать, независимо от результата.

2 голосов
/ 09 мая 2019

Вглубь этого, spec говорит:

TryStatement : try Block Наконец

  1. Пусть B будет результатом оценки Блок .
  2. Пусть F будет результатомоценка Наконец .
  3. Если F . [[type]] нормально, пусть F будет B .
  4. Если F . [[Type]] возвращен или F . [[Type]] - бросок, вернуть Completion ( F ).
  5. Если F . [[Value]] не пусто, вернуть Completion ( F ).
  6. Return Completion {[[type]]: F . [[Type]], [[value]]: undefined , [[target]]: F. [[Target]]}.

Применяя это к вашему testWrapped() коду,

  1. Оценивается блок try.Происходят побочные эффекты print(true), поэтому в консоли будет отображаться true.Возвращается блок try, поэтому результатом его вычисления является Завершение с типом return и значением независимо от того, что print (true) равно: true . Это еще не возвращено.
  2. Блок finally оценивается.То же самое: false в консоли, завершение {[[type]]: return , [[value]]: false }.
  3. «Если F. [[Type]] нормальный» Это не так.Далее.
  4. Здесь действительно происходит возврат, и это возврат из блока finally: false.Конечный результат: true false в консоли, а testWrapped() возвращает false.

И оператор if:

  1. test * tryоценивается блок: Завершение {[[type]]: return , [[value]]: true }.
  2. test s finally blockоценивается: завершение {[[type]]: return , [[value]]: false }.
  3. Nada.
  4. finally Завершение возвращается: ложь.test() оценивается как false, и выполняется блок else.
2 голосов
/ 09 мая 2019

Обе оценены , но на самом деле возвращается .

. Поскольку оценка print() имеет побочный эффект вывода наКонсоль, вы можете увидеть оценку.Но если бы вы были console.log(testWrapped()), вы бы увидели возвращаемое значение после двух оцененных значений.

Ваш код эквивалентен:

try {
    result1 = print(true);
    return result1;
}
finally {
    result2 = print(false);
    return result2;
}

Надеюсь, это прояснит, что происходит.

...