【问题标题】:Closure Compiler: purpose of --language_in and --language_out options?闭包编译器:--language_in 和--language_out 选项的用途?
【发布时间】:2015-05-24 16:44:31
【问题描述】:

Google's Closure Compiler 有以下 CLI 选项:

  • --language_in – 设置输入源符合的语言规范。
  • --language_out – 设置输出应符合的语言规范。

语言

--language_in是什么意思?我认为它是以下之一:

  1. 源代码确实符合指定语言的声明/承诺。编译器不会验证它是否存在;它只是相信它确实如此。
  2. 用于验证源代码是否符合指定语言的编译器指令。如果没有,编译器会报错。

This documentation 似乎暗示意思#1:

项目可以使用--language_in 标志指定他们打算使用的 Ecmascript 语言版本。

但是,this documentation 表示含义 #2(我假设 language webservice 选项连接到 --language_in CLI 选项):

language 参数指的是在检查代码中的错误时采用哪个版本的 ECMAScript。

ECMASCRIPT3 – 假设符合 ECMAScript 3 的情况下检查代码,并使用仅存在于 ECMAScript 5 中的功能为代码提供错误。

如果我使用webservice 编译此代码:

// ==ClosureCompiler==
// @output_file_name default.js
// @compilation_level ADVANCED_OPTIMIZATIONS
// @language ECMASCRIPT3
// ==/ClosureCompiler==

var x = Object.freeze({
    y: 3,
    z: 4
});

console.log(x);

它不会给出Object.freeze() doesn't exist in ECMAScript 3 的错误。为什么不呢?


外语

同样,--language_out 是什么意思?我认为这意味着:

  • 编译器必须生成符合指定语言的输出的指令。

但是如果我编译这段代码:

var x = Object.freeze({
    y: 3,
    z: 4
});

console.log(x);

使用此 CLI 命令,指定 --language_out ECMASCRIPT3:

java -jar compiler.jar \
    --js test.js \
    --js_output_file test.min.js \
    --language_out ECMASCRIPT3 \
    --compilation_level ADVANCED_OPTIMIZATIONS \
    --warning_level VERBOSE \
    --summary_detail_level 3

不会引发错误或警告:

0 error(s), 0 warning(s), 100.0% typed

编译后的代码是:

var a=Object.freeze({y:3,z:4});console.log(a);

所以输出不符合ECMASCRIPT3(因为它包含Object.freeze())。为什么不呢?

【问题讨论】:

  • 试试var foo = {delete: 42};。在 ES3 中,不允许在对象字面量中这样使用保留关键字。

标签: javascript google-closure-compiler


【解决方案1】:

Object.freeze() 的调用不是句法 错误。编译器无法知道您的代码是否在某个时候扩展了 Object 原型。因此Object.freeze() 是完全有效的 ECMAScript 3 代码。

同样,

var x = {};
x.something();

是完全有效的代码。它会在运行时抛出异常,但不是语法错误。

应该说明这些选项的 ES5 特性是在对象字面量中使用保留字作为属性名称:

var x = { if: "hello world" };

另一个是 getter/setter 初始化器:

var x = { get hello() { return "world"; } };

【讨论】:

  • 非常感谢您的回答。我同意对Object.freeze() 的调用不是语法错误。但是对于--language_in ECMASCRIPT3,如果将调用更改为Object.foobar() 之类的名称,编译器会发出警告:JSC_INEXISTENT_PROPERTY: Property foobar never defined on Object。如果您在没有任何参数的情况下调用 Object.freeze(),那么编译器会发出警告:JSC_WRONG_ARGUMENT_COUNT: Function Object.freeze: called with 0 argument(s). Function requires at least 1 argument(s) and no more than 1 argument(s). 所以编译器知道该函数需要 1 个参数。
  • 我认为问题是当指定--language_in ECMASCRIPT3 时编译器不应该使用它的ECMAScript 5 extern。虽然Object.freeze() 不是句法错误,但它应该引发警告:JSC_INEXISTENT_PROPERTY: Property freeze never defined on Object
  • @TachyonVortex 如果它在这些情况下出错,那么我同意它应该禁止 Object.freeze() 用于 ES3 代码。也许它假设您将使用 shim 或其他东西,但如果我是 Closure 用户,我会认为这是一个错误。
  • 目前,无论 language_in 标志如何,我们都使用同一组外部变量。理想情况下,我们有一个简单的标志,您可以在其中指定您的代码将在哪种环境中运行(“网络”,包括旧版浏览器,或“现代网络”,或 node.js 等),您会得到正确的语言模式和正确的外部变量集。目前,您可以使用 --language_in--externs 标志手动指定这些。正如 Pointy 所说,--language_in 控制语言特性和语法,而--externs 指示可用的 API。归档 github.com/google/closure-compiler/issues/966
  • @MatrixFrog 有一个带有通用环境预设的--env 选项当然很好。但list of externs 实际上由两个不同的类别组成:ECMAScript (standard built-in objects)APIs(由 W3C、WHATWG 等定义)。像 Pointy 一样,我认为在指定 --language_in ECMASCRIPT3 时加载 ES5 extern 是一个错误。正如你所说,--language_in 控制语言特性,ES5 extern 定义语言特性(不是 API)。
猜你喜欢
  • 2012-10-27
  • 1970-01-01
  • 2020-09-15
  • 1970-01-01
  • 1970-01-01
  • 2019-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多