Аннотируйте объекты Singleton в JavaScript для компилятора Google Closure, или предупреждение «Опасное использование глобального объекта» - PullRequest
4 голосов
/ 16 апреля 2011

Я работаю с Google Closure Compiler на уровне компиляции ADVANCED_OPTIMIZATIONS и начал комментировать мои конструкторы, потому что я получаю всевозможные предупреждения:

ПРЕДУПРЕЖДЕНИЕ - опасное использование глобального объекта

Для моих функций типа «конструктор» я буду комментировать их следующим образом:

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

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

Это, кажется, работает нормально, но что, если у меня есть объект 'singleton', который не создан с помощью var myFoo = new Foo (); Я не смог найти в документации, как аннотировать этот тип объекта, потому что его тип - просто объект, верно?

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

Ответы [ 2 ]

9 голосов
/ 16 апреля 2011

Предпочтительный способ создания синглетонов в 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.

5 голосов
/ 17 апреля 2011

Это точно тип потенциальной ошибки, от которой вас предупреждает «опасное использование».В вашем примере, 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 в расширенном режиме не пытайтесь избавиться от предупреждений, аннотируя их.Предупреждения существуют по причине - они пытаются вас кое о чем предупредить.

...