JavaScript 语句执行

· 536 words · 3 min

Completion 类型

用一个 try...catch 的例子引出 Completion Record:

function fn() {
  try {
    return 0;
  } catch {
		// do nothing
  } finally {
    return 1;
  }
}

console.log(fn()) // 1

可以看到 try 中的 returnfinally 中的 return 覆盖了, 在一个函数中执行了两次 return。这个现象是基于 JS 语句执行的完成状态 Completion Record。

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

JS 根据语句的 Completion Record,在语句的复杂嵌套结构中,实现各种控制。

普通语句

普通语句可分为声明类语句、表达式语句、空语句、debugger 语句。这些语句是从前往后按顺序执行的, 执行完之后会得到 [[type]] 为 normal 的 Completion Record,JS 引擎遇到这样的 Record 就会继续执行下一条语句。 这些语句中,只有表达式会有返回值,即产生 [[value]]

JavaScript expression return

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

语句块

语句块是语句的复杂结构,可以嵌套。块内语句的 Completion Record 的 [[type]] 如果不为 normal 则会打断后续语句的执行。

// Completion Record([[type]], [[value]])
if(true) {
	const i = 1; // normal, undefined
	i++; // normal, 1
	console.log(i); // normal, undefined
} // normal, undefined

加入了 return 之后:

// Completion Record([[type]], [[value]])
if(true) {
	const i = 1; // normal, undefined
	return i; // return, 1
	i++;
	console.log(i);
} // return, 1

加入了 return 之后,整个结构成为非 normal,穿透了语句嵌套,产生了控制效果。

控制型语句

控制型语句分为两部分,一种是对内部造成影响的比如 ifswitchwhile/fortry 等, 另一种是对外部造成影响的如 breakcontinuereturnthrow 等。两种类型的语句相遇会产生不同的效果。 其中 try...catch 较为特殊,finally 中的内容必须保证执行,try...catch 执行完毕, 即使得到的结果是非 normal 的 Completion Record,也必须要执行 finally 中的内容, 并且会将 finally 执行完的 Completion Record 作为整个 try...catch...finally 的 Completion Record。

From 极客时间