0

Google Closure Compileを使用して ADVANCED_OPTIMIZATIONS で次のコードをコンパイルしています 。

(function() {
  /** @const */
  var DEBUG = false;

  var Namespace = {};
  window['Namespace'] = Namespace;

  (function() {
     /**
      * @constructor
      */
    function Test(tpl) {
      Helper.debug('Test');
    }

    Namespace['Test'] = Test;

  })();

  var Helper = 
    (function(){
       /**
        * @constructor
        */
      function Helper(){
        this.debug = function(arg){
          if(DEBUG){
            console.log(arg);
          }
        }
      };

      return new Helper;
    })();

})();

私の意図は、コンパイラDEBUG == falseDEBUG == true. 私はコンパイラからこのようなものを望んでいます:

DEBUG == false:

var a={};window.Namespace=a;a.Test=function(){};

DEBUG == true:

var a={};window.Namespace=a;a.Test=function(){console.log("Test")};

代わりにこれで終わります:

DEBUG == false:

 var a={};window.Namespace=a;a.Test=function(){b.debug("Test")};var b=new function(){this.debug=function(){}};

DEBUG == true:

var a={};window.Namespace=a;a.Test=function(){b.debug("Test")};var b=new function(){this.debug=function(c){console.log(c)}};

どちらの場合も、debug関数の名前は変更されません。エクスポートされておらず、(私が知る限り)からアクセスできないため、そうあるべきだと思いますNamespaceNamespace.Test()コンストラクタからのみ呼び出されます。そこから呼び出さないと、Closure はデバッグ関数を削除しますが (どこでも使用されていないため)、名前空間の関数を介して呼び出すことができ、名前を変更できるようにしたいと考えています。

上記のコードのさまざまなバージョンを試しました。でprototype.debugを使用しHelper、ヘルパーコンストラクターを名前空間と同じスコープに移動するなど。ただし、デバッグ関数がヘルパーオブジェクトにアタッチされている限り、コンパイラーから目的の出力を取得する方法が見つかりません。

ヘルパー オブジェクトを使用せずdebug、関数として宣言するだけで、目的の出力が正確に得られますが、これは単なる例であり、実際にはヘルパー オブジェクトに関連付けられている多くの関数があり、それらすべてを使用したいと考えています。短い名前に変更されます。希望の出力が得られるコード例:

(function() {
  /** @const */
  var DEBUG = false;

  var Namespace = {};
  window['Namespace'] = Namespace;

  (function() {
     /**
      * @constructor
      */
    function Test(tpl) {
      debug('Test');
    }

    Namespace['Test'] = Test;

  })();

  function debug(arg){
    if(DEBUG){
      console.log(arg);
    }
  }

})();
4

1 に答える 1

1

コードを試してみたところ、名前debugは変換されていませんが、他の名前は変換されることがわかりました。console.log の externs ファイルがないため、console.log を alert に置き換えました。変更したコードは次のとおりです (debug を「something」に、console.log を alert に名前を変更しただけです):

(function() {
  /** @const */
  var DEBUG = false;

  var Namespace = {};
  window['Namespace'] = Namespace;

  (function() {
     /**
      * @constructor
      */
    function Test(tpl) {
      Helper.something('Test');
    }

    Namespace['Test'] = Test;

  })();

  var Helper = 
    (function(){
       /**
        * @constructor
        */
      function Helper(){
        this.something = function(arg){
          if(DEBUG){
            alert(arg);
          }
        }
      };

      return new Helper;
    })();

})();

コードをコンパイルすると、多かれ少なかれ期待される出力が得られます (コンストラクターは使用されません)。

java -jar compiler.jar --js helper.js --js_output_file out.js --compilation_level=ADVANCED_OPTIMIZATIONS --formatting=PRETTY_PRINT --warning_level=VERBOSE

(function() {
  var a = {};
  window.Namespace = a;
  (function() {
    a.Test = function() {
    }
  })()
})();

DEBUG を true に設定すると、次のようになります。

(function() {
  var a = {};
  window.Namespace = a;
  (function() {
    a.Test = function() {
      b.a()
    }
  })();
  var b = function() {
    return new function() {
      this.a = function() {
        alert("Test")
      }
    }
  }()
})();

引用されたプロパティの名前は変更されないことに注意してください。したがって、this['something'] = function(arg){andHelper['something']('Test');を使用すると、何かの名前が変更されなくなります。window['namespace']['Test'] を使用しているため、すでにそれを知っていると思います

[アップデート]

クロージャ コンパイラは、extern で定義されているメソッドの名前を変更しません。たとえば、「ドキュメント」は、コンパイラによって使用される extern で定義されます (そうでない場合、ドキュメントを使用するたびにエラーが発生します)。そのため、名前を変更Helper.debugHelper.getElementByIdても名前は変更されません (getElementById は、コンパイラがデフォルトで使用する externs ファイルで定義されています)。以下は、Oreilly.Closure.The.Definitive.Guide.Sep.2010 の 391 ページのソースです。

var mystery = function(obj) {
alert(obj.max());
};

ミステリーには型情報がないため、obj は組み込みの Math オブジェクトまたは example.NumSet のいずれかになります。Math が Mystery の引数として提供される可能性があるため、コンパイラは max() メソッドの名前を変更できません。このため、コンパイラは変数の名前を変更するための保守的なアプローチを採用しており、externs にも変数が含まれている場合は変数の名前を決して変更しません。これは、コンパイラがデフォルトで追加の externs ファイル (contrib/ externs にあるファイルなど) を含まない主な理由の 1 つです。externs プールに名前を追加すると、コンパイラによって行われる変数の名前変更の量が不必要に減少する可能性があります。

型情報を提供しても、コンパイラはいくつかの追加フラグ --use_types_for_optimization なしでは名前を変更しません。あなたのコードはまだ debug の名前を変更しませんが、それはおそらく typedef が必要だからです。debug の名前を myDebug に変更すると、関数の名前が変更されます。

Closure Compiler が特定の名前のオブジェクトの名前を変更しないのはなぜですか?

于 2013-06-04T00:50:29.917 に答える