在说本章主要讨论的问题之前,先来讲述一下函数中的try/catch/finally分别代表什么:

try:语句测试代码块的错误;

catch:只有当try中的代码块发生错误的时候,才会执行这部分的代码,参数err记录了try内代码块的错误信息;

finally:不管有无异常都会执行内部的代码

介绍完几个关键字代表的含义,我们接着来思考两个问题:

  1. try,catch,finally中return最终会返回谁的结果?
  2. finally中的代码是在 return之前执行,还是之后执行?

看下面的代码:

function func() {try {return 0;} catch (err) {console.log(err)} finally {console.log("a")}
}console.log(func()); 

上面代码中,我们执行函数func(),其打印的结果是什么呢?按照正常的逻辑捋捋,应该是先打印0再打印字符串a,但是结果恰恰相反,上面代码的执行结果是先打印a再打印0。显然,第二个问题我们已经有了答案。finally中的代码会在return语句之前执行。ok,我们再看一段代码:

function func() {try {return 0;} catch (err) {console.log(err)} finally {return 1}
}console.log(func()); 

这时,我们分别在try和finally中放置了return语句,最终的打印结果是1 ,所以上面提的第一个问题的答案就是最终会返回finally中的return结果,咋一看,是finally中有return,所以try和catch中的return语句被finally覆盖了,其实不然,第一个例子告诉我们了代码的执行顺序,finally中的return语句会先执行,而try和catch中的return语句没有在执行,所以最终结果是finally中的return语句。

综合上面的分析,我们可以得到以下几点结论:

  • 在执行任何try和catch中的return语句之前,都会先执行finally中的代码;
  • 如果finally中包含return语句,那么程序就会提前被return出来,所以不建议在finally中放置return语句;
  • 编辑器内会把finally中的return表现为一个warning;

但是,这种执行方式不是很奇怪吗,它的执行方式跟大多数的开发逻辑不相同,导致这种局面的原因就是在于它的执行机制。这个机制的执行基础,就是基于JavaScript中语句的执行完成状态,它可以用一个标准类型来表示:Completion Record,它是用来描述异常或者跳出等语句的执行过程。Completion Record表示一个语句的执行完成后的结果,它有三个字段:

  • [[type]]:表示完成的类型,通常有break,continue,return,throw以及normal几种类型;
  • [[value]]:表示语句的返回值,如果语句没有,则返回empty;
  • [[target]]:表示语句的目标,一般是一个JavaScript标签;

JavaScript 就是依赖Completion Record类型实现各种神奇的控制,下面介绍下使用Completion Record类型,控制语句执行的过程。先从网上抠到一张神图(有关语句的详细分类):

先说下普通语句,普通语句在JavaScript中就是指的不带控制能力的语句,这种语句的执行特点就是从前往后依次执行,在普通语句执行完毕之后,普通语句在执行后,就会得到[[type]]为normal的Completion Record类型,JavaScript引擎解析到的时候,就会继续执行下一条语句。

语句块就是指用大括号括起来的语句,它本质上是一种语句的复合结构,内部可以嵌套。当语句块的内部语句的Completion Record的[[type]]不为normal的话,会打断语句块的后续执行,例如:

{var i = 1 return i i++console.log(i)
}
// 其内部包含return的Completion Record类型,所以直接return 1,后面的语句不会执行

控制型的语句主要分为两部分:一是对其影响内部的,包括if、switch、while/for、try等等;二是对其外部造成影响的,包括break、continue、return、throw等等。这两类语句的配合可以产生控制代码的执行顺序和执行逻辑。

带标签的语句:任何 JavaScript 语句是可以加标签的,在语句前加冒号即可,同时还有就是类似于注释,基本没有任何用处,唯一有作用的时候是:与完成记录类型中的 target 相配合,用于跳出多层循环。

在这些语句中,只有表达式语句会产生 [[value]],当然,从引擎控制的角度,这个 value 并没有什么用处。

最后我们来解释下为什么在finally加入return语句后,为什么得到的结果为1?因为finally中的内容必须保证执行,所以try/catch执行完毕,即使得到的结果是非normal型的完成记录,也必须要执行finally。而当finally执行也得到了非normal记录,则会使finally中的记录作为整个try结构的结果。

JavaScript:执行机制相关推荐

  1. javascript执行机制

    转自:ssssyoki  这一次,彻底弄懂 JavaScript 执行机制 在掘金上讲解js执行机制的文章,收获很多.故复制过来,做复习笔记用 不论你是javascript新手还是老鸟,不论是面试求职 ...

  2. JavaScript 执行机制

    前端开发,一篇文章让你彻底搞懂,什么是JavaScript执行机制!:https://zhuanlan.zhihu.com/p/139261821 大白话讲解 JavaScript 执行机制,一看就懂 ...

  3. 宏事件、微事件、 JavaScript 执行机制

    案例预热: setTimeout(function(){console.log('定时器开始啦')});new Promise(function(resolve){console.log('马上执行f ...

  4. js等待 callback 执行完毕_前端开发,一篇文章让你彻底搞懂,什么是JavaScript执行机制!...

    不论你是javascript新手还是老鸟,不论是面试求职,还是日常开发工作,我们经常会遇到这样的情况:给定的几行代码,我们需要知道其输出内容和顺序.因为javascript是一门单线程语言,所以我们可 ...

  5. 这一次,彻底弄懂 JavaScript 执行机制

    本文的目的就是要保证你彻底弄懂javascript的执行机制,如果读完本文还不懂,可以揍我. 不论你是javascript新手还是老鸟,不论是面试求职,还是日常开发工作,我们经常会遇到这样的情况:给定 ...

  6. 彻底搞懂JavaScript执行机制

    首先我们大家都了解的是,JavaScript 是一门单线程语言,所以我们就可以得出: JavaScript 是按照语句顺序执行的 首先看: let a = '1' console.log(a) let ...

  7. javascript等待异步线程完成_前端:什么是单线程,同步,异步?彻底弄懂 JavaScript 执行机制...

    javascript是按照语句出现的顺序执行的. js是一行一行执行的: let a = '1';console.log(a);let b = '2';console.log(b); 然而实际上js是 ...

  8. animation 先执行一次 在持续执行_这一次,彻底弄懂 JavaScript 执行机制

    本文来源:ssssyokihttps://juejin.im/post/6844903512845860872 不论你是javascript新手还是老鸟,不论是面试求职,还是日常开发工作,我们经常会遇 ...

  9. 一次性搞懂JavaScript 执行机制

    你是否遭受到这样的恐吓? 你是否有过每个表达式前面都console一遍值去找执行顺序? 看了很多js执行机制的文章似乎都是似懂非懂,到技术面问的时候,理不清思绪.总结了众多文章的例子和精华,希望能帮到 ...

  10. 弄懂 JavaScript 执行机制,宏任务和微任务

    本文的目的就是要保证你彻底弄懂javascript的执行机制. 不论你是javascript新手还是老鸟,不论是面试求职,还是日常开发工作,我们经常会遇到这样的情况:给定的几行代码,我们需要知道其输出 ...

最新文章

  1. Struts2 Cannot create a session after the response has been committed 一个不起眼的错误
  2. 图说子图同构算法——VF2算法(一)
  3. SAP RETAIL 我的第一个寄售类型的跨公司采购订单
  4. ubuntu9.10安装文泉驿微米黑字体
  5. OpenStack 虚拟机热迁移流程图
  6. SolrJ商品搜索实现
  7. ios UITableView顶部向下偏移
  8. Python使用Manager对象实现不同机器上的进程跨网络传输数据
  9. DRBD+Corosync+Pacemaker+MySQL(下)
  10. 就业管理系统(Java毕业设计:SpringBoot项目)
  11. ebay 后台HTML有尺寸宽度要求吗,Ebay后台有哪些常用的操作页面?
  12. 【实战】通过命令行调用360杀毒软件接口对指定文件或文件夹杀毒
  13. python3__机器学习__神经网络基础算法__偏执项b
  14. python 战舰_代码战争战舰受损或沉没Python
  15. MySQL数据库如何改名
  16. java后台证件号15转18位
  17. WebBowser 实现淘宝网自动登录
  18. IaaS PaaS SaaS 读音及含义
  19. Mac下配置VIM .vimrc
  20. 送给用 EditPlus 或 Programmer's Notepad 等编辑器写代码的朋友!

热门文章

  1. SQLserver锁和事务隔离级别的比较与使用
  2. Oracle 数据类型 选择自 tjandy 的 Blog
  3. .NET 框架中的字符串(转自MSDN,关于字符串的详细解说!)
  4. 使用内存硬盘(tmpfs)来加速你的网站
  5. 使用命令行 启动 各种服务(控制面板 开机启动项 注册表 等)
  6. Xshell不能链接虚拟机(可ping通)--解决方案
  7. Springboot中关于跨域问题的一种解决方法
  8. Windows无法安装到这个磁盘 选中的磁盘具有MBR分区表解决方法
  9. 如何在sh的字符串中包含换行符?
  10. 为什么git的“ pull request”不称为“ push request”?