为什么JavaScript try / finally块会导致函数明显返回两次?

时间:2019-05-09 18:47:36

标签: javascript node.js function return-value

finally块总是最后执行,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 个答案:

答案 0 :(得分:4)

这是因为您使用的是finally,而不是catch

最后将在尝试或捕获后执行。

在条件块中,它将返回上一个评估的项目false,并执行else块。

请参阅:https://www.w3schools.com/jsref/jsref_try_catch.asp

  

try语句使您可以定义要测试的代码块   在执行时出现错误。

     

catch语句使您可以定义一个代码块   如果try块中发生错误,则执行。

     

finally语句使您可以在尝试捕获之后执行代码,   不管结果如何。

答案 1 :(得分:2)

两者都被评估,但实际上只有第二个被返回

由于print()的评估具有输出到控制台的副作用,因此可以看到评估。但是如果要使用console.log(testWrapped()),则会在两个评估值之后看到返回的值。

您的代码等同于:

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

希望这样可以使事情更清楚。

答案 2 :(得分:2)

深入了解它,spec说:

  

TryStatement try 最终阻止

     
      
  1. B 成为评估 Block 的结果。
  2.   
  3. F 成为对 Finally 求值的结果。
  4.   
  5. 如果 F 。[[type]]正常,则将 F 设为 B
  6.   
  7. 如果返回 F 。[[type]],或者抛出 F 。[[type]],则返回Completion( F )。
  8.   
  9. 如果 F 。[[value]]不为空,则返回Completion( F )。
  10.   
  11. 完成返还{[[type]]: F 。[[type]],[[value]]:未定义,[[target]]:F。 [[target]]}。
  12.   

将此应用于您的testWrapped()代码,

  1. 将评估try块。 print(true)的副作用会发生,因此true将出现在控制台中。 try块返回,因此求值结果是一个Completion,其类型为 return ,且值无论print(true)为:true 这还没有退回。
  2. 将评估finally块。同一件事:控制台中的false,完成{[[type]]:返回,[[value]]: false }。
  3. “如果F。[[type]]正常” 并非如此。接下来。
  4. 这是实际发生退货的地方,它是finally块的退货:false。最终结果:控制台中的true false,并且testWrapped()返回false。

还有if语句:

    评估
  1. test的{​​{1}}块:完成{[[type]]:返回,[[value]]: true }。
  2. 评估
  3. try的{​​{1}}块:完成{[[type]]:返回,[[value]]: false }。
  4. Nada。
  5. test的完成返回:false。 finally的值为finally,并且执行test()块。