JavaScript "编译器"

11

最近我发现了一个很酷的东西,叫做Google Closure Compiler。是否有类似的替代品,可以提供静态类型语言编译所带来的好处?

更新

这不是关于真正的编译器,而是关于JavaScript-JavaScript翻译器,它们提供类型验证等功能、优化和可能的压缩。


3
所谓的 JavaScript 编译器更像是 JavaScript 优化器。代码仍需要在浏览器的 JavaScript 引擎中执行,因此它仍然必须是有效的 JS。它们所能做的就是缩短所有标识符并删除空格以减小文件大小,可能还会在 JS 层面上进行一些微小的优化,但它们永远无法达到编译语言的执行速度。 - Philipp
8
谷歌为什么将它们的工具命名为“编译器”?这肯定会引起混淆。 - Lee Taylor
1
@David - 是的,编译后的代码比JS运行速度更快 - 为什么不是呢?你为什么认为在你的电脑上情况相反呢? - nnnnnn
1
@SperanskyDanil "不能"?这是一个很高的说法。请记住,最先进的JavaScript解释器能够在观察到实际特征后重写它们生成的机器代码以优化常用路径。这是您的C++编译器无法做到的,并且完全可以相信,在某些边缘情况下,它将导致更好的运行时性能;现代JIT编译引擎可以做一些非常令人印象深刻的事情,而AOT编译器则无法做到。 - Charles Duffy
7
Closure Compiler 被称为编译器,因为它执行了你期望从 C++ 编译器中看到的所有功能(例如类型检查、死代码消除、函数和变量内联等),唯一的区别是它生成 JavaScript 而不是机器码。JavaC 也不会生成机器码,而是生成字节码,JavaC 的工作仅限于类型检查和生成字节码(将几乎所有优化留给 JVM)。从概念上讲,Closure 编译器实际上比 Java 编译器更接近于优化的 C++ 编译器。 - John
显示剩余7条评论
4个回答

6

根据你的评论:

我对类型检查、接口检查、私有字段检查等感兴趣,所有这些都可以让你编写安全的代码,而不仅仅是最小化。

JavaScript 是一种动态类型语言,没有内置支持类、接口或访问修饰符。Closure Compiler 通过使用嵌入在 JSDoc 注释中的信息支持各种特殊功能,例如接口和访问修饰符。几个 IDE 也使用 JSDoc 标签信息提供静态分析,例如,请参见 WebStorm & PhpStorm 博客:5.0 新功能:Google Closure Compiler JSDoc 注释

在 JavaScript 压缩器领域,有诸多选择,例如YUI CompressorUglifyJSdojo shrinksafeMicrosoft Ajax MinifierJSMIN。然而,这些工具都不提供与 Closure Compiler 相同水平的基于 JSDoc 的分析支持。

相关的 stack overflow 问题:

  1. 哪个 Javascript 压缩器(cruncher)与 Google 用于其 JS API 的压缩器相同?
  2. 有哪些适用于生产代码的好的 CSS 和 JS 最小化器?
  3. JavaScript 的类型检查器?
  4. 有一个好的 JavaScript 压缩器吗?
  5. JavaScript 和 CSS 最小化器
  6. JavaScript 压缩
  7. JavaScript 静态类型检查的当前状态是什么?

2
Closure Compiler(谷歌)是一款真正的JavaScript编译器。其他选择包括TypeScript(微软)和Flow(Facebook)。Closure Compiler使用jsdoc注释来注释类型。TypeScript使用不同于es3/es5的语法提供类型注释,然后将其编译为纯JavaScript。Flow利用OCaml语言(在类型推断方面表现出色)来尽可能地推断类型信息,但也可以使用注释语法来消耗注释。Closure Compiler也在努力改进类型推断,但目前还没有准备好用于生产。
针对@EASI的回应:Closure Compiler是一个真正的编译器,而不仅仅是代码压缩工具。它的工作方式如下:
1. 解析一组输入.js文件和一组外部文件(定义了ecma 3,5,6和常见浏览器对象(如Window等)的接口)成为抽象语法树(AST)。
2. 对AST运行一系列编译器通道,进行重写、转换、消除死代码等操作。
3. 将AST发回到js源代码中。它将把文件连接在一起并删除注释(WHITESPACE_ONLY),在函数定义中重命名和缩小符号(SIMPLE),或将所有符号重命名和重写为缩小和混淆的形式(ADVANCED)。
以下是编译器通道的列表,供感兴趣的人参考。正如您所看到的,有很多事情要做。

AliasExternals.java 别名外部 AliasStrings.java 别名字符串 AmbiguateProperties.java 模糊属性 AnalyzeNameReferences.java 分析名称引用 AnalyzePrototypeProperties.java 分析原型属性 AstValidator.java Ast验证器 CallGraph.java 调用图 ChainCalls.java 链式调用 CheckConformance.java 检查符合性 CheckDebuggerStatement.java 检查调试器语句 CheckEventfulObjectDisposal.java 检查有事件的对象处理 CheckGlobalNames.java 检查全局名称 CheckMissingGetCssName.java 检查缺少getCssName CheckRegExp.java 检查正则表达式 CheckSideEffects.java 检查副作用 ClosureCodeRemoval.java 闭包代码移除 ClosureOptimizePrimitives.java 闭包优化基元 CollapseAnonymousFunctions.java 折叠匿名函数 CollapseProperties.java 折叠属性 CollapseVariableDeclarations.java 折叠变量声明 ConstCheck.java 常量检查 ConstParamCheck.java 常量参数检查 ConvertDeclaredTypesToJSDoc.java 将声明类型转换为JSDoc ConvertToDottedProperties.java 转换为点属性 ConvertToTypedES6.java 转换为类型化的ES6 CoverageInstrumentationPass.java 覆盖率仪器传递 CreateSyntheticBlocks.java 创建合成块 CrossModuleCodeMotion.java 跨模块代码运动 CrossModuleMethodMotion.java 跨模块方法运动 DeclaredGlobalExternsOnWindow.java 在窗口上声明全局外部 DefaultPassConfig.java 默认传递配置 Denormalize.java 反归一化 DisambiguateProperties.java 消除属性歧义 ErrorPass.java 错误传递 Es6ToEs3ClassSideInheritance.java ES6到ES3类侧继承 ExpandJqueryAliases.java 扩展JQuery别名 ExportTestFunctions.java 导出测试函数 ExternExportsPass.java 外部导出传递 ExtractPrototypeMemberDeclarations.java 提取原型成员声明 FlowSensitiveInlineVariables.java 流敏感内联变量 FunctionNames.java 函数名称 FunctionRewriter.java 函数重写器 GatherExternProperties.java 收集外部属性 GatherRawExports.java 收集原始导出 GenerateExports.java 生成导出 GlobalNamespace.java 全局命名空间 GlobalTypeInfo.java 全局类型信息 GroupVariableDeclarations.java 组变量声明 ImplicitNullabilityCheck.java 隐式可为空性检查 InferConsts.java 推断常量 InjectEs6RuntimeLibrary.java 注入ES6运行时库 InlineFunctions.java 内联函数 InlineObjectLiterals.java 内联对象文字 InlineProperties.java 内联属性 InlineVariables.java 内联变量 InstrumentFunctions.java 仪器函数 JsMessageVisitor.java Js消息访问者 MarkNoSideEffectCalls.java 标记无副作用调用 MethodCompilerPass.java 方法编译器传递 MinimizeExitPoints.java 最小化退出点 NameAnalyzer.java 名称分析器 NameAnonymousFunctions.java 命名匿名函数 NameAnonymousFunctionsMapped.java 命名匿名函数映射 NameReferenceGraphConstruction.java 名称引用图构建 NewTypeInference.java 新类型推断 Normalize.java 归一化 ObjectPropertyStringPostprocess.java 对象属性字符串后处理 ObjectPropertyStringPreprocess.java 对象属性字符串预处理 OptimizeArgumentsArray.java 优化参数数组 OptimizeCalls.java 优化调用 OptimizeParameters.java 优化参数 PeepholeOptimizationsPass.java 窥视孔优化传递 PhaseOptimizer.java 阶段优化器 PrepareAst.java 准备AST ProcessCommonJSModules.java 处理CommonJS模块 ProcessDefines.java 处


我可能是在纠结小事(俗话说),但我认为您列出的第三项基本上让您的论点无效了。编译器通常会将人类可读的语言转换为机器码。当Closure“编译器”将其所有工作转换回JavaScript时,那么这个新代码只会在普通的JavaScript引擎上运行,对吧?我并不是说Closure “编译器”所做的工作不是广泛的,而且非常接近常规编译器所做的工作,但最终它只是重构JavaScript,而不是“编译”它。 - Quantium

0

0

是的,

有Java、JS、PHP、CSS和HTML的"压缩器"。 例如,当您使用Google GWT Java进行编程时,代码会生成为JS的最小化。


他们使用编译器这个术语,但这并不正确。编译器将一种人类可读的语言代码转换为只有解释器或机器可以读取的目标代码。Google工具所做的是优化您的代码,以便解释器可以更快地读取它。脚本语言需要解释器才能执行。编译成机器语言的程序比任何解释器都要快地执行。但当然,任何程序的速度都取决于其执行流程项目和开发团队的经验。

新消息:

您是否尝试过在专门的IDE中编写JavaScript代码? 如果您正在寻找类型检查,可以尝试以下之一:

  • NuSphere PhpED Professional v7(最佳)
  • phpDesigner 8
  • Aptana Studio
  • Zend Studio
  • DreamWeaver CS6

它们现在具有更好的支持,不仅支持PHP,还支持JavaScript,具有代码自动完成、类型验证、动态语法高亮、多语言语法高亮和面向对象分析以及随打随完成功能。


5
Closure Compiler在基本模式下作为“最小化器”,但在高级模式下,它确实像一个真正的编译器一样工作,只不过目标语言是JavaScript而非字节码或机器码。它不仅仅有一个窥视优化器,还有代码路径/可达性分析、函数内联等所有你期望一款优化编译器要做的事情。 - Charles Duffy
@SperanskyDanil,请尝试访问http://fmarcia.info/jsmin/test.html。 - NaN
1
@CharlesDuffy,GCC是最先进的编程工具。就像一些机器人读取您的软件,然后将其重建为更好的5倍。这就是谷歌使其Gmail成为出色的Web 2.0服务的方式。 - NaN
@EASI 闭包编译器在高级模式下具有自己的类型验证、接口检查等功能,如果使用适当的注释,您可以考虑一些相关链接。 - Charles Duffy
6
请大家不要将 Google Closure Compiler 称为 "GCC"。Unix 有自己的 GCC(GNU 编译器集合),这可能会引起混淆。请注意区分。 - Camilo Martin
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接