《重学前端》学习笔记(6)

JavaScript执行(四):Completion 类型

语句是任何编程语言的基础结构,与 JavaScript 对象一样,JavaScript 语句同样具有“看起来很像其它语言,但是其实一点都不一样”的特点。

Completion 类型

  • try中有return语句,finally 中的内容还会执行吗?

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

    finally确实执行了,而且 return语句也生效了,foo() 返回了结果 0

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

  • finally中加入return 语句,会发生什么呢?

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

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

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

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

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

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

JavaScript 正是依靠语句的 Completion Record类型,方才可以在语句的复杂嵌套结构中,实现各种控制。

语句分类

在这里插入图片描述
在这里插入图片描述

  • 普通的语句

    1. 普通语句在执行时,从前到后顺次执行(我们这里先忽略var和函数声明的预处理机制),没有任何分支或者重复执行逻辑。

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

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

    4. 使用 chrome 自带的调试工具,可以知道,输入一个表达式,在控制台可以得到结果,但是在前面加上var,就变成了undefined。Chrome 控制台显示的正是语句的 Completion Record 的 [[value]]

  • 语句块

    1. 语句块就是拿大括号括起来的一组语句,它是一种语句的复合结构,可以嵌套。

    2. 语句块本身并不复杂,我们需要注意的是语句块内部的语句的 Completion Record 的 [[type]]如果不为normal,会打断语句块后续的语句执行。

    3. 在一个 block 中,如果每一个语句都是 normal 类型,那么它会顺次执行。但是假如我们在 block 中插入了一条return语句,产生了一个非normal记录,那么整个 block会成为非normal。这个结构就保证了非normal 的完成类型可以穿透复杂的语句嵌套结构,产生控制效果。

  • 控制型语句

    1. 控制型语句带有 ifswitch关键字,它们会对不同类型的 Completion Record 产生反应。

    2. 控制类语句分成两部分,一类是对其内部造成影响,如 ifswitchwhile/fortry。另一类是对外部造成影响如 breakcontinuereturnthrow,这两类语句的配合,会产生控制代码执行顺序和执行逻辑的效果,这也是我们编程的主要工作。

    3. 一般来说,for/while - break/continuetry - throw这样比较符合逻辑的组合,是大家比较熟悉的,但是,实际上,我们需要控制语句跟 breakcontinuereturnthrow四种类型与控制语句两两组合产生的效果。

    在这里插入图片描述

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

  • 带标签的语句

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

      firstStatement: var i = 1;
      

      大部分时候,这个东西类似于注释,没有任何用处。唯一有作用的时候是:与完成记录类型中的 target相配合,用于跳出多层循环。

发布了33 篇原创文章 · 获赞 73 · 访问量 2772

猜你喜欢

转载自blog.csdn.net/weixin_46124214/article/details/104202031
今日推荐