Javascript模块模式和Google Closure编译器

mpd*_*dio 1 javascript drupal google-closure-compiler

我现在正在Drupal项目上使用Google Closure Compiler.我的Javascript使用Javascript模块模式构建.

由于Drupal的工作方式,我正在单独编译每个JS文件.简单编译模式运行良好,但我想在每个文件上使用高级编译.

我的文件都是变体

var FOO = (function(me, $, Drupal, undefined) {
  function init (context, settings) {
    do_sutff();
  };

  Drupal.behaviors['FOO'] = {
    attach: init
  };

  return me;
}(FOO || {}, jQuery, Drupal));
Run Code Online (Sandbox Code Playgroud)

我的问题是Drupal.behaviorsDrupal中的一个特定对象,该attach属性也是一个特定的属性.当Drupal页面呈现时,Drupal.behaviors循环遍历,并attach使用正确的参数调用所有函数.换句话说,我不希望任何用Drupal对象重命名的东西.

当我使用高级编译模式时,我得到了

var c = function(a, d, b) {
  b.b.FOO = {a:function() {
    do_stuff()
  }};
  return a
}(c || {}, jQuery, Drupal);
Run Code Online (Sandbox Code Playgroud)

我试图让编译器将整个Drupal对象识别为extern而没有运气,尝试了许多变体.不管我怎么努力,.behaviors.attach始终获得改名.

有没有办法告诉编译器保持完整的对象?

Cha*_*rth 5

没有概念"不要修改此对象的任何属性".但是,您可以设置extern,例如:

/** @interface */
function DrupalBehavior() {}
DrupalBehavior.prototype.attach = function(){};

/** @constructor */
function DrupalObject () {}

/** @type {Object.<string, DrupalBehavior>} */    
DrupalObject.prototype.behaviors = {};
Run Code Online (Sandbox Code Playgroud)

然后,在您的代码中:

var FOO = (
   /**
    * @param {Object} me
    * @param {jQuery} $
    * @param {DrupalObject} Drupal
    * @param {*=} undefined
    */
   function(me, $, Drupal, undefined) {
     function init (context, settings) {
       do_sutff();
     };
     Drupal.behaviors['FOO'] = {
       attach: init
     };

     return me;
  }(FOO || {}, jQuery, Drupal));
Run Code Online (Sandbox Code Playgroud)

在这种情况下,Drupal参数将被重命名,但behaviors属性及其相关的attach子属性将不会被重命名.

关于jQuery的一点说明:您将jQuery名称空间对象作为参数传递给函数.Closure-compiler不会在此对象中很好地跟踪类型.我列出的注释将用于jQuery对象的实例,而不是整个jQuery命名空间.这可能不是你想要的.在Closure-compiler中处理此问题的唯一类型安全方法是不通过函数闭包传递名称空间.

更新:在查看链接的JavaScript模块模式后,他们鼓励将全局命名空间对象传递到函数闭包中.这种模式已知Closure-compiler的问题.您需要选择遵循这方面的模式,或选择与ADVANCED_OPTIMIZATIONS完全兼容.