看一个如下的例子。在函数 foo 中,使用了一组 try 语句。在 try 中有 return 语句,finally 中的内容还会执行吗?

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

得到的结果是:a 0。

根据结果可以看出finally执行了,return语句也生效了。

虽然 return 执行了,但是函数并没有立即返回,又执行了 finally 里面的内容,这样的行为违背了很多人的直觉。

我们改一下上面的例子,在finally也加入return语句,如下:

function foo(){
try{
return 0;
} catch(err) { } finally {
return 1;
}
}

得到的结果是:1

通过实际执行,我们看到,finally 中的 return “覆盖”了 try 中的 return。在一个函数中执行了两次 return,这已经超出了很多人的常识,也是其它语言中不会出现的一种行为。

面对如此怪异的行为,我们当然可以把它作为一个孤立的知识去记忆,但是实际上,这背后有一套机制在运作。

这一机制的基础正是 JavaScript 语句执行的完成状态,我们用一个标准类型来表示:Completion Record(Completion Record 用于描述异常、跳出等语句执行过程)。

Completion Record 表示一个语句执行完之后的结果,它有三个字段:

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

JavaScript 正是依靠语句的 Completion Record 类型,方才可以在语句的复杂嵌套结构中,实现各种控制。接下来我们要来了解一下 JavaScript 使用 Completion Record 类型,控制语句执行的过程。

语句的分类如下:

普通语句执行后,会得到 [[type]] 为 normal 的 Completion Record,JavaScript 引擎遇到这样的 Completion Record,会继续执行下一条语句。

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

如果你经常使用 chrome 自带的调试工具,可以知道,输入一个表达式,在控制台可以得到结果,但是在前面加上 var,就变成了 undefined。

Chrome 控制台显示的正是语句的 Completion Record 的 [[value]]。

现在解释下在finally也加入return语句后,为什么得到的结果为1?

因为 finally 中的内容必须保证执行,所以 try/catch 执行完毕,即使得到的结果是非 normal 型的完成记录,也必须要执行 finally。

而当 finally 执行也得到了非 normal 记录,则会使 finally 中的记录作为整个 try 结构的结果。

带标签的语句的作用:与完成记录类型中的 target 相配合,用于跳出多层循环。

实际上,任何 JavaScript 语句是可以加标签的,在语句前加冒号即可:

firstStatement: var i = 1;

跳出循环的例子:

top:
for (var i = 0; i < 3; i++){
for (var j = 0; j < 3; j++){
if (i === 1 && j === 1) break top;
console.log('i=' + i + ', j=' + j);
}
}
// i=0, j=0
// i=0, j=1
// i=0, j=2
// i=1, j=0

小tips:在JS语句执行机制涉及的一种基础类型Completion的更多相关文章

  1. JS 引擎执行机制

    JS JS 是单线程语音 JS 的 Event Loop 是 JS 的执行机制.类似于 Android Handler 消息分发机制 JS 单线程 技术的出现都跟现实世界里的应用场景密切相关 JS 单 ...

  2. 浅析JS异步执行机制

    前言 JS异步执行机制具有非常重要的地位,尤其体现在回调函数和事件等方面.本文将针对JS异步执行机制进行一个简单的分析. 从一份代码讲起 下面是两个经典的JS定时执行函数,这两个函数的区别相信对JS有 ...

  3. 小tips:JS之浅拷贝与深拷贝

    浅拷贝: function extendCopy(p) { var c = {}; for (var i in p) { c[i] = p[i]; } return c; } 深拷贝: functio ...

  4. 深入理解 JS 引擎执行机制(同步执行、异步执行以及同步中的异步执行)

    首先明确两点: 1.JS 执行机制是单线程. 2.JS的Event loop是JS的执行机制,深入了解Event loop,就等于深入了解JS引擎的执行. 单线程执行带来什么问题? 在JS执行中都是单 ...

  5. JS代码执行机制

    JS代码从编译到执行 我们写出一段JS代码,JS的引擎并不是按照我们书写的顺序从上到下顺序编译并且执行的,首先是按照自己的规则对我们的代码先进行编译,然后从上到下执行编译的代码. 在全局作用域中,JS ...

  6. js的执行机制

    遇到一个问题,因为自己本身就是菜鸟的原因,弄懂了还是很高兴的. console.log(a) function a() { return "this is function" } ...

  7. 小tips:JS数值之间的转换,JS中最大的Number是多少?,JS == 与 === 的区别

    JS数值之间的转换 Number(), parseInt(),parseFloat() Number()函数的转换规则如下: 1.如果boolean值,true和false将分别被转换为1和02.如果 ...

  8. 小tips:JS之break,continue和return这三个语句的用法

    break语句 break语句会使运行的程序立刻退出包含在最内层的循环或者退出一个switch语句.由于它是用来退出循环或者switch语句,所以只有当它出现在这些语句时,这种形式的break语句才是 ...

  9. 小tips:JS中typeof与instanceof用法

    介绍 typeof typeof用以获取一个变量或者表达式的类型,typeof一般只能返回如下几个结果: number boolean string function(函数) object(NULL, ...

随机推荐

  1. 06-numpy-笔记-shape

    shape 是返回 np.mat 的形状的. 1. 作为 mat 的成员变量,a.shape 2. 作为 np 的成员函数,np.shape >>> import numpy as ...

  2. NOIP 2015 推销员

    洛谷 P2672 推销员 洛谷传送门 JDOJ 2994: [NOIP2015]推销员 T4 JDOJ传送门 Description 阿明是一名推销员,他奉命到螺丝街推销他们公司的产品.螺丝街是一条死 ...

  3. JS常用关键字总结

    in: 案例1.遍历对象: for(key in obj) { console.info( key+":"+obj[key]; ) }; 案例2.判断对象中是否有属性: " ...

  4. pychram-redis破解

    1. Preferences -> Plugins-> 选择右下角Browse repositories 2. 搜索Iedis 3. 找到Iedis插件目录:C:\Users\用户名\.P ...

  5. ABP 往前端返回详细的错误信息

    在这个类:MyABP.Web.Startup.MyABPWebMvcModule 中 的 PreInitialize 方法 添加一句: Configuration.Modules.AbpWebComm ...

  6. Linux下进程间通信方式——pipe(管道)

    每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程A把数据从用户空间拷到内核缓冲区,进程B再从内核缓冲区把 ...

  7. 回溯法 | n皇后问题

    今早上看了一篇英语阅读之后,莫名有些空虚寂寞冷.拿出算法书,研读回溯法.我觉得n皇后问题完全可以用暴力方式,即先对n个数进行全排列,得到所有结果的下标组合,问题规模为n!. 全排列花了比较久的时间才编 ...

  8. PyTorch学习之六个学习率调整策略

    PyTorch学习率调整策略通过torch.optim.lr_scheduler接口实现.PyTorch提供的学习率调整策略分为三大类,分别是 有序调整:等间隔调整(Step),按需调整学习率(Mul ...

  9. varnish搭建cdn网络-------3.0.5版本

    CDN分发网络CDN的全称是Content Delivery Network,即内容分发网络.其基本思路是尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输的更快.更稳定.通过在 ...

  10. Spring Security教程(一)

    一 概要 Spring Security,这是一种基于 Spring AOP 和 Servlet 过滤器的安全框架.它提供全面的安全性解决方案,同时在 Web 请求级和方法调用级处理身份确认和授权.这 ...