欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

throw/try/catch/finally 语句

程序员文章站 2022-04-06 16:03:06
...

异常:发生了某种异常情况或错误时产生的一个信号。

抛出异常:用信号通知发生了错误或异常状况。(使用 throw 语句)

捕获异常:采取必要的手段处理这个信号。(使用 catch 语句)

throw/try/catch/finally 语句

throw 语句作用:显式地抛出异常。

throw 语法throw exception;exception 的值是任意类型)


try/catch/finally 语句是 JS 的异常处理机制。

try:定义了需要处理的异常所在的代码块。

catch:当 try 块内某处发生了异常时,调用 catch 内的代码逻辑。

finally:不管 try 块中是否发生异常,finally 块内的逻辑总是执行。

注意:catch 从句和 finally 从句是可选的,但 try 从句需要至少两者之一组成完整的语句。也就是说,try 从句不能单独存在。


JS 解析器抛出异常的时候通常采用 Error 类型或其子类型。Error 的 name 属性表示错误类型,message 属性表示错误的提示信息。

function fun(x) {
  // 如果输入参数是非法的,则抛出一个异常
  if (x < 0) throw new Error('x 不能是负数')
  return x
}
fun(-1);

throw/try/catch/finally 语句

上面代码中,输入的 x 是非法的,程序通过 throw 语句显示的抛出一个异常。


当抛出异常时,JS 解析器会立即停止当前正在执行的逻辑,并跳转至最近的异常处理程序。

function fun(x) {
  try {
    if (x < 0) {
      console.log('第4行:此行代码可以执行...')
      throw new Error('发生异常...')
      console.log('第6行:此行代码无法执行...')
    }
  } catch (e) {
    console.log('第9行:异常在此被捕获--' + e)
  }
}
fun(-1)

throw/try/catch/finally 语句

上面代码中,由于 throw 从句会抛出一个异常并停止正在执行的逻辑,所以第6行不会被执行。抛出的异常会被 catch 从句捕获并处理。


如果抛出异常的代码块没有相关联的 catch 从句,解析器会检查更高层的闭合代码块是否有异常处理程序。以此类推,直到找到异常处理程序为止。否则,JS 会把该异常当做程序错误来处理,并报告给用户。

function fun1 (x) {
    if (x < 0) {
      throw new Error('此异常发生在 fun1 中...')
    }
}

function fun2 (x) {
  try {
    fun1(x);
  } catch (e) {
    console.log('在 fun2 中处理异常:' + e)
  }
}

fun2(-1)

throw/try/catch/finally 语句

上面代码中,fun2 在 内部中调用了 fun1。程序在 fun1 中抛出异常,但是该代码块中没有异常处理程序,解析器会向上一层(fun2)代码块中检查,所以异常会被 fun2 中的 catch 从句捕获并处理。


不管是 try 从句中是否产生异常,finally 从句内的逻辑总是会执行。

function fun () {
  try {
    console.log('try')
  } finally {
    console.log('finally')
  }
}

fun()

throw/try/catch/finally 语句

上面代码中,try 从句中的逻辑不发生异常,之后会接着执行 finally 从句中的逻辑。


如果在 try 从句中发生了异常,并存在相关联的局部 catch 从句,解析器会先执行 catch 从句中的逻辑,然后执行 finally 从句中的逻辑。

function fun () {
  try {
    throw new Error('try 中发生异常...')
  } catch (e) {
    console.log('在 catch 中捕获异常:' + e);
  } finally {
    console.log('finally: 我都会被执行')
  }
}

fun()

throw/try/catch/finally 语句

上面代码中,try 从句中抛出异常,被局部 catch 从句捕获并处理,接着执行 finally 从句中的逻辑。


如果不存在处理异常的局部 catch 从句,解析器会首先执行 finally 中的逻辑,然后向上传播这个异常,直到找到能处理这个异常的 catch 从句。

function fun1 () {
  try {
    throw new Error('try:不行了,我要抛出异常了...')
  } finally {
    console.log('finally:先执行我,再传播异常...')
  }
}

function fun2 () {
  try {
    fun1()
  } catch (e) {
    console.log('catch:嘻嘻,又捕获到一个小笨蛋--' + e)
  }
}

fun2()

throw/try/catch/finally 语句

上面代码中,try 从句中抛出异常,但没有局部 catch 从句处理异常,所以会先执行 finally 从句,然后被上一层的 catch 从句捕获。


当由于 returncontinuebreak 语句使得解析器跳出 try 从句时,解析器在执行新的目标代码之前会先执行 finally 从句中的逻辑。

function fun1 () {
  try {
    return 'cez'
  } finally {
    console.log('finally: 在执行新的目标代码之前,会先执行我哦...')
  }
}

function fun2 () {
  fun1()
  console.log('新的目标代码:我执行在 finally 从句之后哦...')
}

fun2()

throw/try/catch/finally 语句


如果在 tryfinally 从句中都抛出异常,finally 中的异常将替代 try 中的异常。

function fun1 () {
  try {
    throw new Error('在 try 中抛出异常...')
  } finally {
    throw new Error('在 finally 中抛出异常...')
  }
}

function fun2 () {
  try {
    fun1()
  } catch (e) {
    console.log('catch:'+ e)
  }
}

fun2()

throw/try/catch/finally 语句

如果 finally 从句中有 return 语句,尽管抛出了异常并且这个异常还没有处理,但这个方法依然会正常返回。

function fun1 () {
  try {
    throw new Error('在 try 中抛出异常...')
  } finally {
    return 'finally'
  }
}

function fun2 () {
  try {
    console.log(fun1())
  } catch (e) {
    console.log('catch:' + e)
  }
}

fun2()

throw/try/catch/finally 语句

如果 finally 中有 return 语句,则该方法会有正常的返回值,并且 try 中抛出的异常将不会被更高层的 catch 从句捕获到,但会被局部的 catch 从句捕获,如下:

function fun1 () {
  try {
    throw new Error('在 try 中抛出异常...')
  } catch (e) {
    console.log('局部 catch:' + e)
  } finally {
    return 'finally'
  }
}

function fun2 () {
  console.log(fun1())
}

fun2()

throw/try/catch/finally 语句

此时 try 中抛出的异常会被局部 catch 从句捕获。

相关标签: js javascript