问题“Google Closure Compiler 如何处理引号(字符串文字)?” 也可以改写为:
- 为什么 Closure 用双引号替换/交换单引号?
- Closure 如何决定使用哪种引用格式/样式?
- (如何)我可以改变这个(默认)行为吗?
注1:这个问题不是关于为什么闭包(或其他一些缩小器)选择更喜欢双引号(如here和here所问)。
注意 2:这个问题不是关于单引号和双引号的讨论,但是了解 GCC 对我们的代码做了什么(以及为什么)是相当有用的!
人们经常说(或问为什么)G oogle C losure C ompiler (GCC) 用双引号替换单引号(即使compilation_level
设置为WHITESPACE_ONLY
!!!):
示例xmp_1.js:
alert('Hello world!'); // output: alert("Hello world!");
然而......这只是“真相”的一半,因为:
示例xmp_2.js:
alert('Hello "world"!'); // output: alert('Hello "world"!');
// *NOT*: alert("Hello \"world\"!");
GCC 本质上是一个“你的原始 javascript”到“更小(更高效)的 javascript”的翻译器:所以它不会“盲目地”用双引号替换单引号,而是尝试选择一个“最佳引号字符”(毕竟。 . 主要目标之一是“缩小”脚本)。
从源代码(CompilerOptions.java)和这个问题报告中可以了解到:
如果字符串包含的单引号多于双引号,则编译器将使用双引号包裹字符串,反之亦然。
如果字符串不包含引号或包含相同数量的单引号和双引号,那么编译器将默认使用双引号。
像这个例子xmp_3.js:
alert('Hello "w\'orld"!'); // output: alert('Hello "w\'orld"!');
alert('Hello "w\'o\'rld"!'); // alert("Hello \"w'o'rld\"!");
请注意上面的 xmp_3 如何导致使用'
和"
作为外部引号的“混合”输出:最佳选择后跟默认值(当它无关紧要时)。
事实证明,在一些严重的真实案例中,默认使用单引号会更好。正如上面引用的问题 836(从 2012 年 10 月 8 日起)中所解释的:
FT Web 应用程序 (app.ft.com) 和适用于 Playbook 的 Economist 应用程序通过将 JavaScript 更新与其他资源一起作为 JSON 编码对象的一部分传输给客户端。JSON 原生使用双引号,因此编译后的 JavaScript 中的所有双引号都需要转义。在传输大更新时,这会使 FT 网络应用程序的 JS 的大小膨胀约 20kB。
问题的记者带来了一份礼物:一个补丁,添加了prefer_single_quotes
将默认引号字符从双引号更改为单引号的选项。
这个问题被认真对待,以至于项目成员 Santos考虑将默认的双引号更改为单引号('看看是否有人抱怨').. TWICE(也在记者/补丁贡献者声明他将其作为一个选项实施之后,以便它不会产生任何向后兼容的后果,因为“出于某种奇怪的原因,有人可能会依赖用双引号输出的字符串”)。
然而,大约一周后补丁被接受(r2258),又一周后重新设计(r2257),2012 年 10 月 30 日,Santos 报告说现在可以启用该选项:(所以除了-key之外还有
第三个选项)。
(注意:在当前的源代码中,目前仍然可以找到大量对“prefer_single_quotes”的引用。)
--formatting=SINGLE_QUOTES
PRETTY_PRINT
PRINT_INPUT_DELIMITER
formatting
用法:
如果您(下载并)使用(本地 java)应用程序:
java -jar compiler.jar --js xmp_1.js --formatting SINGLE_QUOTES
你会看到:alert('Hello world!');
现在编译为alert('Hello world!');
但是,在撰写本文时,位于http://closure-compiler.appspot.com的编译器服务 API 和 UI(很可能使用该 API)不接受这第三个(新的,虽然存在一年)格式化选项:SINGLE_QUOTES
并且会抛出错误:
17: Unknown formatting option single_quotes.
在(再次)挖掘源代码之后,似乎(我不是 Java 专家)这是因为jscomp/webservice/common/Protocol.java只接受旧的PRETTY_PRINT
和PRINT_INPUT_DELIMITER
* All the possible values for the FORMATTING key.
*/
public static enum FormattingKey implements ProtocolEnum {
PRETTY_PRINT("pretty_print"),
PRINT_INPUT_DELIMITER("print_input_delimiter"),
;
如果此选项在 API 和/或 UI 中可用,我将更新此答案。
希望这有助于并节省一些时间,因为谷歌可以找到的唯一文档和参考SINGLE_QUOTES
目前在这一期 836 和源代码中的一些评论中。现在它对SO有一些解释(我期望它)。