4

ADVANCED_OPTIMIZATIONS コンパイル レベルで Google Closure Compiler を使用しており、あらゆる種類の警告が表示されるため、コンストラクターに注釈を付け始めました。

警告 - グローバルな this オブジェクトの危険な使用

「コンストラクタ」タイプの関数については、次のように注釈を付けます。

/**
 * Foo is my constructor
 * @constructor
 */
Foo = function() {
   this.member = {};
}

/**
 * does something
 * @this {Foo}
 */
Foo.prototype.doSomething = function() {
   ...
}

それはうまくいくようですが、 var myFoo = new Foo(); で構築されていない「シングルトン」オブジェクトがある場合はどうなりますか? このタイプのオブジェクトに注釈を付ける方法をドキュメントで見つけることができませんでした。そのタイプは単なるオブジェクトですよね?

Bar = {
   member: null,
   init: function() {
      this.member = {};
   }
};
4

2 に答える 2

9

Closure でシングルトンを作成する好ましい方法は次のとおりです。

/** @constructor */
var Bar = function() { };
goog.addSingletonGetter(Bar);

Bar.prototype.member = null;

Bar.prototype.init = function() {
  this.member = {};
};

これにより、シングルトンの遅延インスタンス化が可能になります。次のように使用します。

var bar1 = Bar.getInstance();
var bar2 = Bar.getInstance();

bar1.init();
console.log(bar2.member);

これは、コンストラクターを使用して のインスタンスを作成することを妨げるものではないことに注意してくださいBar

于 2011-04-16T16:13:07.370 に答える
5

これはまさに、「これの危険な使用」が警告するタイプの潜在的なバグです。あなたの例では、Closure Compilerコードを次のように「平坦化」しようとする場合があります。

Bar$member = null;
Bar$init = function() { this.member = {}; };

注: Closure Compiler は現在、グローバル オブジェクトとして宣言されている名前空間 (つまり、"var" キーワードが前にない) を平坦化しないため、コードは今でも機能する可能性があります。ただし、将来のバージョンでそれが行われなくなり、コードが警告なしに突然壊れるということはわかりません。

もちろん、"Bar$member" と "Bar$init" はそれぞれ "a" と "b" に名前が変更されます。これは、「名前空間の平坦化」または「プロパティの崩壊」と呼ばれます。

コードが正しく機能しなくなったことはすぐにわかります。コンパイルする前に、次のように記述します。

Bar.init();

thisを参照しBarます。ただし、コンパイル後は次のようになります。

Bar$init();

thisを参照しなくなりますBar。代わりに、グローバル オブジェクトを参照します。

これは、「this」が「グローバル」オブジェクトを参照するように変更される可能性があるため、「this」をそのような方法で使用することは「危険」であることをコンパイラが警告しようとしている方法です。それが警告の本当の意味です。

要するに、これをしないでください。このタイプのコーディング スタイルでは、追跡が非常に困難なバグが発生します。

コードを次のように変更します。

var Bar = {    // Closure Compiler treats globals and properties on global differently
  member: null,
  init: function() { Bar.member = {}; }
};

またはクロージャーを使用します。

var Bar = (function() {
  var member = null;
  return {
    init: function() { member = {}; }
  };
})();

Closure Compiler を Advanced Mode で使用する場合、注釈を付けて警告を取り除こうとしないでください。警告には理由があります。何かについて警告しようとします。

于 2011-04-17T03:41:18.680 に答える