for (let i = 0; i < 100; i++) {
    if (i === 50) break;
}

相信大家在使用break的场景是类似上面的场景,在for循环中在特定的判断下跳出循环。

image.png

相信大家都在console上这样操作过,输入这些语句的结果究竟是什么。
答案是Completion Record
Completion Record是EMCScript标准中的一个规范类型。
它长这个样子

{
[[Type]]: normal | continue | break | return | throw
[[Value]]: 语句执行的结果,如果没有则是empty
[[Target]]: 控制流的转移目标,通常是标签
}

语句的执行都会产生一个Completion Record
在一个Block中,也会返回一个Completion Record

{
    let a = 1; // 1
    console.log(a); // 2
    ++2; // 3
    console.log(a); // 4
}

大家直接把上面的代码复制在chrome 的console中然后执行,看结果是什么?
结果是2,现在我们逐步分析一下
在上面的块级作用域中,位置1产生的Completion Record

[[Type]]: normal,
[[Value]]: empty,
[[target]]: nothing

按照上面的逻辑,位置2的[[Value]]是empty
位置3的[[Value]]是2
位置4的[[Value]]是empty
empty不会覆盖之前的结果
所以整个块级作用域的执行结果是2

现在有一个提案是do表达式

const w = do {
    let a = 1;
    ++2;
};

能够获取块级作用域Completion Record[[Value]]
如果这个提案通过的话,之后的JSX将抛弃长长的三目判断
image.png

image.png

上面这个代码,如果执行foo函数输出的内容是什么?
在 try中进行return,由于存在finally,而finally无论如何都是需要被执行的,所以try的Completion Record

[[Type]]: return,
[[Value]]: 100,
[[target]]: nothing

执行到finally的时候,整个try-catch-finally代码块的Completion Record

[[Type]]: break,
[[Value]]: empty,
[[target]]: bbb

所以return会被break覆盖
最终返回的i是101


一画先生
83 声望12 粉丝

我司长期招聘前端开发工程师,有意的小伙伴+vx: Mr_yihua