美文网首页JavaScript
[JS] try-catch-finally 的不常见用法

[JS] try-catch-finally 的不常见用法

作者: 何幻 | 来源:发表于2019-10-21 18:05 被阅读0次

trycatchfinally,有一些不太常见的使用方式。
我们来总结下,在这些场景,程序会怎样表现。

1. 可省语句块

catchfinally 可省,但是不能都省略

// 省略 catch
try {

} finally {

}
// 省略 finally
try {
  
} catch (e) {  // 只能写一个参数

}
// 省略形参
try {
  
} catch {  // 不写形参

} finally {

}

注:
(1)trycatchfinally中,如果没有 return 也没有 throw
还会执行 try-catch-finally 语句块后面的代码。

(2)没有 catch 的情况下,如果 try 抛异常,则外层函数会直接抛异常。

(3)catch 的形参只能写一个,不能写多个,形参的名字可以不是 e
即,不能写 catch () {,也不能写 catch (e, c) {

(4)catch 可省略形参,即,catch {

(5)finally 中的代码总会执行,不论 trycatch 是否 returnthrow

2. 提前返回

trycatchfinally 中的 return 会导致函数直接返回

// try直接返回
(() => {
  try {
    console.log(1);
    return 2;  // try -> finally -> 返回try中的return
  } catch (e) {
    console.log(3);
  } finally {
    console.log(4);
  }
  console.log(5);
  return 6;
})();  // 1 4
// 返回:2
// catch直接返回
(() => {
  try {
    console.log(1);
    throw 2;
  } catch (e) {
    console.log(3);
    return 4;  // try -> catch -> finally -> 返回catch中的return
  } finally {
    console.log(5);
  }
  console.log(6);
  return 7;
})();  // 1 3 5
// 返回:4
// finally直接返回
(() => {
  try {
    console.log(1);
  } catch (e) {
    console.log(2);
  } finally {
    console.log(3);
    return 4;  // try -> finally -> 返回finally中的return
  }
  console.log(5);
  return 6;
})();  // 1 3
// 返回:4

注:
(1)trycatchfinally中都可以写 return
try-catch-finally 语句块后面的代码就不执行了,外层函数直接返回。

(2)即使 trycatch 中写了 returnfinally 也会执行完再 return

3. 提前抛异常

try 中抛异常,但是 catch 没捕获;catchfinally 里的 throw
会导致函数直接抛异常

// try抛异常,省略了catch
(() => {
  try {
    console.log(1);
    throw 2;  // 抛出try中的throw
  } finally {
    console.log(3);
  }
  console.log(4);
  return 5;
})();  // 1 3
// 异常:Uncaught 2
// catch抛异常
(() => {
  try {
    console.log(1);
    throw 2;
  } catch (e) {
    console.log(3);
    throw 4;  // try -> catch -> finally -> 抛出catch中的throw
  } finally {
    console.log(5);
  }
  console.log(6);
  return 7;
})();  // 1 3 5
// 异常:Uncaught 4
// finally抛异常
(() => {
  try {
    console.log(1);
  } catch (e) {
    console.log(2);
  } finally {
    console.log(3);
    throw 4;  // try -> finally -> 抛出finally中的throw
  }
  console.log(5);
  return 6;
})();  // 1 3
// 异常:Uncaught 4

注:
(1)trycatchfinally中都可以写 throw
或者 try 中抛异常,但是 catch 没捕获,
try-catch-finally 语句块后面的代码就不执行了,外层函数直接抛异常。

(2)即使 trycatch 中写了 throwfinally 也会执行完再 throw

4. 覆盖返回值或异常

finally 中的 returnthrow 会覆盖 trycatch 中的 returnthrow

// finally return 覆盖 try return
(() => {
  try {
    console.log(1);
    return 2;  // 丢弃
  } catch (e) {
    console.log(3);
  } finally {
    console.log(4);
    return 5;  // try -> finally -> 返回finally中的return
  }
  console.log(6);
  return 7;
})();  // 1 4
// 返回:5
// finally return 覆盖 try throw(省略了catch时)
(() => {
  try {
    console.log(1);
    throw 2;  // 丢弃
  } finally {
    console.log(3);
    return 4;  // try -> finally -> 返回finally中的return
  }
  console.log(5);
  return 6;
})();  // 1 3
// 返回:4
// finally throw 覆盖 try return
(() => {
  try {
    console.log(1);
    return 2;  // 丢弃
  } catch (e) {
    console.log(3);
  } finally {
    console.log(4);
    throw 5;  // try -> finally -> 抛出finally中的throw
  }
  console.log(6);
  return 7;
})();  // 1 4
// 异常:Uncaught 5
// finally throw 覆盖 try throw(省略了catch时)
(() => {
  try {
    console.log(1);
    throw 2;  // 丢弃
  } finally {
    console.log(3);
    throw 4;  // try -> finally -> 抛出finally中的throw
  }
  console.log(5);
  return 6;
})();  // 1 3
// 异常:Uncaught 4
// finally return 覆盖 catch return
(() => {
  try {
    console.log(1);
    throw 2;
  } catch (e) {
    console.log(3);
    return 4;  // 丢弃
  } finally {
    console.log(5);
    return 6;  // try -> catch -> finally -> 返回finally中的return
  }
  console.log(7);
  return 8;
})();  // 1 3 5
// 返回:6
// finally return 覆盖 catch throw
(() => {
  try {
    console.log(1);
    throw 2;
  } catch (e) {
    console.log(3);
    throw 4;  // 丢弃
  } finally {
    console.log(5);
    return 6;  // try -> catch -> finally -> 返回finally中的return
  }
  console.log(7);
  return 8;
})();  // 1 3 5
// 返回:6
// finally throw 覆盖 catch return
(() => {
  try {
    console.log(1);
    throw 2;
  } catch (e) {
    console.log(3);
    return 4;  // 丢弃
  } finally {
    console.log(5);
    throw 6;  // try -> catch -> finally -> 抛出finally中的throw
  }
  console.log(7);
  return 8;
})();  // 1 3 5
// 异常:Uncaught 6
// finally throw 覆盖 catch throw
(() => {
  try {
    console.log(1);
    throw 2;
  } catch (e) {
    console.log(3);
    throw 4;  // 丢弃
  } finally {
    console.log(5);
    throw 6;  // try -> catch -> finally -> 抛出finally中的throw
  }
  console.log(7);
  return 8;
})();  // 1 3 5
// 异常:Uncaught 6

注:
(1)try-catch-finally 语句块的返回值由 finally 决定,只要 finally 中有 return (即使是 return undefined;)或 throw,则 trycatch 中的 returnthrow 都会被覆盖。

(2)return 可以覆盖 throwthrow 也可以覆盖 return


总结

finally 总是会执行,执行完了以后,再根据 finally,确定返回值,以及是否抛异常。

相关文章

  • [JS] try-catch-finally 的不常见用法

    try,catch 和 finally,有一些不太常见的使用方式。我们来总结下,在这些场景,程序会怎样表现。 1....

  • JS递归的常见用法

    递归的概念 在程序中函数直接或间接调用自己直接调用自己间接调用自己 跳出结构,有了跳出才有结果 递归的思想 递归的...

  • JavaScript八张思维导图

    目录 JS基本概念 JS操作符 JS基本语句 JS数组用法 Date用法 JS字符串用法 JS编程风格 JS编程实...

  • 温故而知新,8张 Javascript 思维导图助你成长

    目录 JS基本概念 JS操作符 JS基本语句 JS数组用法 Date用法 JS字符串用法 JS编程风格 JS编程实...

  • Moment.js常见用法总结

    Moment.js常见用法总结 Moment.js是一个轻量级的JavaScript时间库,它方便了日常开发中对时...

  • JS之DOM常见用法

    修改样式 可以修改元素的style属性,修改结果直接反映到页面元素 获取样式 使用getComputedStyle...

  • js 循环

    js中forEach,for in,for of循环的用法 js的 for...in 和 for...of的用法 ...

  • 深入解析ES Module

    不要使用 export default {a, b, c} 一个常见的错误如下 错误用法1 # lib.js ex...

  • js的内置对象和常见用法

    Date对象(时间创建对象) Math类(相当于静态工具) 字符串:

  • JavaScript八张思维导图

    JavaScript八张思维导图 目录 JS基本概念 JS操作符 JS基本语句 JS数组用法 Date用法 JS字...

网友评论

    本文标题:[JS] try-catch-finally 的不常见用法

    本文链接:https://www.haomeiwen.com/subject/xlitvctx.html