try...catch...finally对return和throw Error的处理

2,491 阅读2分钟

try...catch...finally 组合使用时,如果他们的代码块中有return或者抛出异常时会怎么样呢?

first 🌰

一般情况

function foo () {
  try {
    console.log('run try')
  } catch (error) {
    console.log(error)
  }
  finally{
    console.log('run finally')
  }
  console.log('run foo')
}
console.log(foo())
// run try
// run finally
// run foo
// undefined

上面的代码,先执行 try 中的代码,打印 run try, 没有异常抛出,进入 finally ,打印 run finally,最后执行打印 run foo。函数执行结束,没有返回值,打印 undefined

second 🌰

try 中有return

function foo () {
  try {
    return 1
  } catch (error) {
    console.log(error)
  }
  finally{
    console.log('run finally')
  }
  console.log('never run')
}
console.log(foo())
// run finally
// 1

上述代码先执行try,把函数foo 的返回值设置为1,然后执行finally,打印 run finally,因为函数有返回值了,结束运行,打印返回值 1

third 🌰

finally中有 return

function foo () {
  try {
    return 1
  } catch (error) {
    console.log(error)
  }
  finally{
    console.log('run finally')
    return 2
  }
  console.log('never run')
}
console.log(foo())
// run finally
// 2

上面的代码在 finally 中加入了 return 2,最终函数的返回值为 2,覆盖了 try 中的返回值。

结论一:

try...finally 组合使用时,如果 finally 中设置了返回值,此返回值会覆盖 try 中的返回值,没有设置的话就不会覆盖

fourth 🌰

try 中抛出异常

function foo () {
  try {
    throw 0
    return 1
  } catch (error) {
    console.log(error)
  }
  finally{
    console.log('run finally')
  }
  console.log('run foo')
}
console.log(foo())
// 0
// run finally
// run foo
// undefined

上面的代码 try 中抛出异常,return 1 没有执行,进入 catch 流程,打印 0,然后进入 finally 流程,打印 run finally ,此时函数还没有返回值,继续执行打印 run foo , 最后函数执行完毕,打印 undefined

如果在 finally中加入 return 2, 那么函数返回值会是 2

fifth 🌰

finally中抛出异常

function foo () {
  try {
    return 1
  } catch (error) {
    console.log(error)
  }
  finally{
    console.log('run finally')
    throw 2
  }
  console.log('never run')
}
console.log(foo())
// run finally
// Uncaught 2

上面的代码 finally中抛出异常,函数就此终止。异常没有被捕获,后面的程序结束执行。同时,try中函数的返回值 1 被丢弃

结论二:

如果 finally 中抛出异常(无论是有意还是无意),函数就会在此处终止。如果此前 try 中 已经有 return 设置了返回值,则该值会被丢弃。