JavaScript

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

2019-10-21  本文已影响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,确定返回值,以及是否抛异常。

上一篇 下一篇

猜你喜欢

热点阅读