再问你一遍,你真的了解try..catch(finally)吗???

定义

首先来看下 MDN 的定义:javascript

The try...catch statement marks a block of statements to try and specifies a response should an exception be thrown.前端

try...catch语句标记要执行的语句,并指定一个当有异常抛出时候的响应java

简短的一句的确描述了try...catch的大部分功能。less

可是,最MDN的最后,有一段话是这么写的:ide

Returning from a finally-block函数

If the finally-block returns a value, this value becomes the return value of the entire try-catch-finally statement, regardless of any return statements in the try and catch-blocks. This includes exceptions thrown inside of the catch-block:ui

finally语句块的返回值this

若是finally语句块中有返回值,那么这个值将做为整个try...catch语句的返回,不管try语句块或者catch语句块中是否有返回,这包括了catch中的异常。spa

ok,那咱们就尝试加上return,看看会发生什么。3d

case1

输入
function fn() {
  try {
    console.log('try块内log');
  } catch (error) {
    console.log('catch块内log');
  } finally {
    console.log('finally块内log====');
  }
  return '通常状况下的return';
}
console.log(fn());
复制代码
输出:

一切看起来都如咱们所想,没有问题,继续往下看。

case2

输入
function fn() {
  try {
    console.log('try块内log');
    return 'try中的return'; // <=== 多了这么一句
  } catch (error) {
    console.log('catch块内log');
    return 'catch中的return语句';
  } finally {
    console.log('finally块内log====');
  }
  return '通常状况下的return';
}
console.log(fn());
复制代码
输出

正如上图所示,这里打印的是try的return,可是,finally语句块中的log依然被执行了。 看到这里,咱们能够知道,finally的执行时机是在try(或者cache,cache同理)执行return以前被执行。 那咱们就能够验证下MDN上所说的:finally语句块的返回值 这句话的真正含义。

case3

输入
function fn() {
  try {
    console.log('try块内log');
    return 'try中的return'
  } catch (error) {
    console.log('catch块内log');
    return 'catch中的return语句';
  } finally {
    console.log('finally块内log====');
    return 'finaly中的return'; // <=== 多了这么一句
  }
  return '通常状况下的return';
}
console.log(fn());
复制代码
输出

ok,依然很正常,由于finally会在try的return以前执行,因此拦截了try中的return,打印了finally中的return

你觉得这样就结束了吗?

咱们继续往下看。

case4

输入
function justLog(){
  console.log('来自justLog的打印');
  return '来自justLog的return'
}

function fn() {
  try {
    console.log('try块内log');
    return justLog(); // <=== 此次咱们return了一个函数
  } catch (error) {
    console.log('catch块内log');
    return 'catch中的return语句';
  } finally {
    console.log('finally块内log====');
    return 'finaly中的return';
  }
  return '通常状况下的return';
}
console.log(fn());
复制代码

先思考一下会打印什么?看看是否和真实的输出一致。给咱们几秒钟...







小小的声援一下,但愿战'役'早日胜利。加油! 而后: 我会长期更新有趣的,有料的前端知识,若是对你有帮忙,请关注我,往后接受第一手更新消息。很是感谢







输出

你答对了没有? 能够看到,红框内为justLog函数的log,红框下面是finally中的打印和返回。 因此finally真正的执行时机是:try(或catch)中 return关键字以前。 因此咱们才看到了justLog中的打印。 有关return关键字的实现,能够自行查询标准,这里不赘述。

应用场景

好比咱们有这样一个高阶函数:

function hoc(fn) {
  return fn()
}
复制代码

咱们想要返回所传递参数的执行结果,这样作是没问题的。

那若是咱们想在函数执行以后,return以前,作一些其余操做,应该怎么作呢?

function hoc(fn) {
  const res = fn();
  // 其余操做
  return res;
}
复制代码

很简答,咱们能够先获取返回值,再进行其余操做,而后return。 不过这样咱们就占用了额外的空间,并且没法便利的复用return后的语句,这个时候,咱们的try...catch就能够排上用场了:

function hoc(fn) {
  try {
    return fn();
  } finally {
    // 一些其余操做,这些操做会在 `fn()执行后,return执行前` 被执行
  }
}
复制代码

总结

大白话来说,finally语句块会在try(或catch)中的 return 关键字以前执行。一图以概之:

最后,若是有帮到你的地方,欢迎关注、交流。

相关文章
相关标签/搜索