如何解决Google Closure命名空间地狱?

 中国脐橙在线 发布于 2023-02-03 09:20

我的新工作是使用Google Closure库编写面向组件的JavaScript.我喜欢活动,组件,服务和模块.但由于需要编写混乱使用命名空间的代码,因此工作非常苛刻.以下代码是典型的:

goog.provide(com.bin.slash.dot.closure.widget.SuperForm);

goog.require(com.bin.slash.dot.closure.widget.Avatar);
// ... ten require calls more...

com.bin.slash.dot.closure.widget.SuperForm = function() {
  goog.base(this);
  this._internal = new com.bin.slash.dot.closure.widget.Avatar(
    com.bin.slash.dot.closure.widget.Avatar.SRC_PATH);
};

我无法相信这是真的.我并不害怕输入所有这些,但我只是觉得逻辑在这个符号地狱中消失了.扫描非常困难,因此需要更多时间来了解正在发生的事情.我的老板说,不鼓励写下以下快捷方式:

var SF = com.bin.slash.dot.closure.widget.SuperForm = function(){};

因为所有这些都将在编译后绑定到全局命名空间(窗口),因此它们可能会干扰其他内容.

问题是如何避免这个符号地狱?

更新:我改进了我的开发人员流程,解决了地狱的问题.现在我编写了甜蜜的JavaScript,然后由Grunt使用sweet.js宏自动编译:

// For each file I define three macros which are replaced 
// in the compile time with hell of a long paths.
macro dir { rule { $x } => { my.very.very.long.namespace $x } }
macro class { rule { $x } => { dir.NameOfMyClass $x } }
macro proto { rule { $x } => { class.prototype $x } }

dir.NameOfMyClass = function() {}; // yields: my.very.very.long.namespaceNameOfMyClass = function() {};
class.CONSTANT = "I don't know why we write constants into classes, not prototypes"; // yields: my.very.very.long.namespaceNameOfMyClass.CONSTANT = ...;
proto.method1 = function() {}; // yields my.very.very.long.namespaceNameOfMyClass.prototype.method1 = function(){};

宏编译器创建的所有噪声都被优秀的shelljs删除.

1 个回答
  • 假设您正在使用Closure Compiler,请考虑goog.scope.有内置的编译器支持,可在优化之前替换别名变量:

    Closure Library更简洁goog.scope - 来自Closure Library wiki的设计文档

    谷歌JavaScript风格指南:别名与 goog.scope

    文档 goog.scope

    Closure Library代码中的源代码示例

    在一个要点

    goog.providegoog.require语法没有改变;

    您可以在范围内开始声明非构造函数名称空间;

    构造函数名称空间需要在重命名它们的作用域之外声明.

    考虑到上述指南,您的代码示例可能看起来像这样:

    goog.provide('my.very.long.namespace.NameOfMyClass');
    goog.require('my.very.long.namespace');
    
    /** @constructor */
    my.very.long.namespace.NameOfMyClass = function() { /*...*/ };
    
    goog.scope(function() {
      var _ = my.very.long.namespace.NameOfMyClass;
    
      _.CONSTANT = 'I don\'t know why we write constants into classes, not prototypes';
    
      _.prototype.method1 = function() {};
    
    }); // goog.scope
    

    额外

    由于我没有足够的声誉来添加评论:

    我的老板说,不鼓励写下以下快捷方式:

    var SF = com.bin.slash.dot.closure.widget.SuperForm = function(){};
    

    因为所有这些都将在编译后绑定到全局命名空间(窗口),因此它们可能会干扰其他内容.

    即使没有这些快捷方式,高级编译也可以重命名符号,例如SFmyVariable简单ga.这可能会导致与Google Analytics等外部代码发生冲突.

    Closure支持的防止全局范围内此类冲突的方法是编译引入一个立即调用的函数表达式(源代码).使用编译器标志:--output_wrapper "(function(){%output%})();"或符合严格模式的变体:--output_wrapper "(function(){%output%}).call(this);".使用时,老板不鼓励的快捷方式可以避免与外部符号发生冲突.

    2023-02-03 09:24 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有