【问题标题】:Why does Babel 6 some (unnecessary) code transformations为什么 Babel 6 会进行一些(不必要的)代码转换
【发布时间】:2015-11-16 14:27:23
【问题描述】:

在这个简单的 Babel (6.1.18) 示例中,babel --presets es2015 test.js 转换:

'use strict'; // enable strict mode

(function () {
    const A = 3;
}());

'use strict' // enable strict mode
;
(function () {
    var A = 3;
})();

这主要是出于好奇,但我有兴趣更好地理解原因: - 第一行中分号的位置已移到单独的行中 - iife 的语法已从(function () {}()); 更改为(function () {})();

【问题讨论】:

  • 它并不是真的决定转换这段代码,而它本来可以保持原样......它是 Babel 总是使用特定的语法来输出特定的结构。您的输入被解构为抽象语法树,然后重新组合成 Javascript 代码。这里的“汇编器”被硬编码为输出这些特定情况。就这样。你可能会问为什么它以这种特定的格式输出东西,但担心为什么把这个输入具体转换成这个输出是没有意义的。

标签: javascript ecmascript-6 babeljs


【解决方案1】:

抽象语法树不保留格式信息,例如调用括号是在分组运算符的外部还是内部。其实分组运算符((...))就是not even represented in the AST

这就是人们致力于Concrete Syntax Tree implementation 的原因,其中将包含此类信息以及代码生成器可以使用哪些信息来更接近原始源代码。

如果那部分代码没有改变,有些工具可以重用原始代码(例如recast),但由于 Babel 主要专注于为浏览器转译代码,这可能不太重要。现在 Babel 更像是一个平台,这可能会改变。

【讨论】:

  • 这正是我感兴趣的。Babel 从 AST 重新生成代码。假设 Babel 在编译我的代码时使用了最少侵入性的方法,这显然是我的一厢情愿。我想没有人会真正关心,但我非常感谢一种“重铸”方法,其中只进行绝对必要的更改,并且我的代码尽可能多地保留“我的”代码。谢谢!
【解决方案2】:

Babel 是一个转译器,其工作方式与编译器非常相似:

  1. Babel 对您的代码执行词法分析。这意味着它被标记化了。 (function(){})() 变成了一个令牌流,例如"(" "function" "(" ")" ...

  2. babel 创建一个语法树。代表您的程序的线性标记流被转换成这样的树:

  3. babel 然后对你的代码进行语义分析。这是它检查错误、确保您的代码是合法的 ECMA6 代码、添加缺少的分号并确保语法树是合法程序的时候

  4. babel 从语法树生成 javascript 代码

因此,您可以看到有几种方法可以编写相同的代码,但是在执行语义分析和代码生成时,会生成相同的代码。

【讨论】:

  • 我确实了解 Babel 的工作原理,但希望它在不需要时能减少干扰。我用我给定的例子来展示 Babel 实际上不需要转译任何东西的 2 个案例。我的文件的语法树已经包含一个“use strict”语句,并且 iife 生成了相同的代码。
  • 好吧,但是(function () {}()); 的语法树与(function () {})(); 不同——它不仅仅是空格。所以肯定有其他事情发生。
  • @Bergi:它是相同的语法树,至少遵循 ESTree 规范。
  • @FelixKling:所以 ESTree 省略了分组运算符?好的,这似乎是合理的。
猜你喜欢
  • 2020-04-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-24
  • 2012-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-08
相关资源
最近更新 更多