Babel的奇妙冒险 @babel/babel-plugin-transform-for-of

293 阅读1分钟

前置知识

如果接触过 python 中迭代器和生成器,或者 Rxjs 中的观察者和迭代器模式,看到 JavaScript 中的 function* yield* 和迭代协议应该会会心一笑。

相关 AST spec

interface ForOfStatement <: ForInStatement {
  type: "ForOfStatement";
  await: boolean;
}

interface ForStatement <: Statement {
  type: "ForStatement";
  init: VariableDeclaration | Expression | null;
  test: Expression | null;
  update: Expression | null;
  body: Statement;
}

用途

解析 for...of 语法

源码解析

源代码

代码比较长,这里就不整段贴了,gitee传送门

插件通过 option assumeArray 的值实现了两种 visitor,部分UT代码代码如下:

  • assumeArray == true 通过js代码,实现ForOfStatement转为ForStatement
  • assumeArray == false 通过模板的方式实现转换
assumeArray == true
// input
for (const i of items) i;

// output
for (let _i = 0, _array = array; _i < _array.length; _i++) {
  const elm = _array[_i];
  console.log(elm);
}
assumeArray == false
// input
for (i of arr) {

}

// output
var _iterator = babelHelpers.createForOfIteratorHelper(arr),
    _step;

try {
  for (_iterator.s(); !(_step = _iterator.n()).done;) {
    i = _step.value;
  }
} catch (err) {
  _iterator.e(err);
} finally {
  _iterator.f();
}

有耐心的同学可以通过AST explorer生成AST语法树,结合Babel 插件开发手册,对比源码进行阅读。