小tips:在JS语句执行机制涉及的一种基础类型Completion

看一个如下的例子。在函数 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

原文地址:https://www.cnblogs.com/moqiutao/p/10916381.html

时间: 2024-10-14 00:51:16

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

JS 引擎执行机制

JS JS 是单线程语音 JS 的 Event Loop 是 JS 的执行机制.类似于 Android Handler 消息分发机制 JS 单线程 技术的出现都跟现实世界里的应用场景密切相关 JS 单线程 JS 最初被设计用在浏览器中,相当于在 UI 线程,设计成多线程就涉及到同步的问题,很复杂,假如不同步的话, UI 线程就不安全.所以设计成了单线程 JS 为什么需要异步 JS 因为是单线程的,可以在 IO 等操作,但是因为是耗时操作,所以会出现卡死的情况,所以为了不影响用户体验,所以需要设计

JS代码执行机制

JS代码从编译到执行 我们写出一段JS代码,JS的引擎并不是按照我们书写的顺序从上到下顺序编译并且执行的,首先是按照自己的规则对我们的代码先进行编译,然后从上到下执行编译的代码. 在全局作用域中,JS首先会对我们的函数进行声明,然后就是我们经常听到的变量提升机制,然后才是按照我们书写代码的顺序,来进行编译,然后在执行编译的代码. 看如下代码: function fn(){ console.log(a); } fn(); var a = "value"; 非常常见的一个面试题fn函数执行

浅析JS异步执行机制

前言 JS异步执行机制具有非常重要的地位,尤其体现在回调函数和事件等方面.本文将针对JS异步执行机制进行一个简单的分析. 从一份代码讲起 下面是两个经典的JS定时执行函数,这两个函数的区别相信对JS有一定基础的同学是十分清楚的.timeout仅仅只会执行一次,而interval则会执行多次. setTimeout(function (args) { console.log('timeout') }, 1000); setInterval(function (args) { console.log

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

浅拷贝: function extendCopy(p) { var c = {}; for (var i in p) { c[i] = p[i]; } return c; } 深拷贝: function deepCopy(p, c) { var c = c || {}; for (var i in p) { if (typeof p[i] === 'object') { c[i] = (p[i].constructor === Array) ? [] : {}; deepCopy(p[i], c

Javascript 中js语句执行顺序

如果我们把嵌入在HTML中的<script> js coding </script>看做Js代码块(实际上Js没有代码块的意义一说,如果真要看成代码块那也应该是按函数块来划分)的话,下面就是Js代码执行顺序: 这里转载 Js执行顺序总结归纳  请参考  http://www.3lian.com/edu/2014/04-07/139469.html  step 1.  读入第一个代码块<script> js coding </script>,按HTML中声明的

js的执行机制

进程 应用程序 都可以算是一个进程 几乎所有的应用程序都是多进程 线程 每个进程里的最小单位就是线程 多线程好 共作效率高,但是js这门语言是操作dom,就相当于我们盖房子,前面的没盖好,后面的就没法操作.单线程,有一处出现问题,后面的都需要等待. 为了解决单线程出现的问题js提供了同步和异步这两个概念 同步执行:前一个任务执行完了,才能执行后一个任务,这种事同步执行 相当于盖房子 异步执行:前一个任务执行时花费时间过长,无需等待,执行下一个任务,这时异步.相当于做饭,煮饭的时候还可以炒菜. J

小tips:js中的Navigator对象

Navigator 对象包含有关浏览器的信息. 注释:没有应用于 navigator 对象的公开标准,不过所有浏览器都支持该对象. Navigator 对象属性: 属性 描述 appCodeName 返回浏览器的代码名. appMinorVersion 返回浏览器的次级版本. appName 返回浏览器的名称. appVersion 返回浏览器的平台和版本信息. browserLanguage 返回当前浏览器的语言. cookieEnabled 返回指明浏览器中是否启用 cookie 的布尔值.

小tips:JS == 与 === 的区别

1.对于string,number等基础类型,==和===是有区别的1)不同类型间比较,==之比较“转化成同一类型后的值”看“值”是否相等,===如果类型不同,其结果就是不等2)同类型比较,直接进行“值”比较,两者结果一样 2.对于Array,Object等高级类型,==和===是没有区别的进行“指针地址”比较 3.基础类型与高级类型,==和===是有区别的1)对于==,将高级转化为基础类型,进行“值”比较2)因为类型不同,===结果为false

js执行机制

1.     关于javascript js是一门单线程语言,一切js版的'多线程'都是用单线程模拟起来的. 2.     js事件循环 将任务分为2类:同步任务.异步任务 同步任务进入主线程,异步任务进入Event Table并注册函数 当指定的事件完成时,Event Table会将这个函数移入Event Queue 主线程内的任务执行完毕为空后,会去Event Queue读取对应的函数,进入主线程运行 以上过程会不断的重复,即Event Loop事件循环 js引擎存在monitoring p