Каков предпочтительный способ определения свойств для классов Google Closure?

В приведенном ниже примере показан класс, расширяющий goog.ui.Component.

Должны ли свойства класса определяться вне конструктора, как показано ниже, или они должны определяться только внутри конструктора?

Можно ли инициализировать свойства нулем?

goog.provide("org.something.SomeClass");

/**
 * @type {Object}
 * @private
 **/
org.something.SomeClass.prototype.anObject_ = null;

/**
 * @type {Element}
 * @private
 **/
org.something.SomeClass.prototype.anElement_ = null;

/**
 * @param {goog.dom.DomHelper=} opt_domHelper
 * @constructor
 * @extends {goog.ui.Component}
*/
org.something.SomeClass = function () {
    goog.ui.Component.call(this, opt_domHelper);

    this.anObject_ = {};
    this.anElement_ = new Element();
};
goog.inherits(org.something.SomeClass, goog.ui.Component);

person Odinodin    schedule 31.08.2012    source источник


Ответы (2)


библиотека закрытия реализует классы со свойствами, определенными в прототипе, а также в функции-конструкторе. Помимо изучения исходного кода библиотеки Closure, вот несколько вопросов, которые следует учитывать при принятии решения о том, следует ли определять свойство в прототипе или в конструкторе.

Является ли свойство уникальным для каждого экземпляра класса?

Свойства, уникальные для каждого экземпляра (например, VIN-номер автомобиля), не должны использоваться совместно между экземплярами и поэтому определяются в конструкторе, а не в прототипе.

/**
 * A car.
 * @param {string} vin The Vehicle Identification Number.
 * @constructor
 */
Car = function(vin) {

  /**
   * The Vehicle Identification Number.
   * @type {string}
   * @private
   */
  this.vin_ = vin;
}; 

Является ли тип свойства неизменным (например, строка, логическое значение, число) или изменяемым (например, объект, массив)?

Поскольку неизменяемые типы свойств можно безопасно использовать между экземплярами, они должны быть определены в прототипе. Если экземпляру необходимо переопределить общее значение по умолчанию, может быть добавлено свойство экземпляра, которое затеняет свойство прототипа с тем же именем.

/**
 * The number of cylinders in the engine.
 * @type {number}
 * @private
 */
Car.prototype.cylinders_ = 4;

/**
 * Sets the number of cylinders in the engine.
 * @param {number} cylinders The number of cylinders.
 */
Car.prototype.setCylinders = function(cylinders) {
  if (this.cylinders_ == cylinders) {
    // Since the number of cylinders has not changed, do not add a new
    // instance property to shadow the prototype property. Instead, continue
    // to use the prototype property.
    return;
  }

  // Defines cylinders_ property on the instance object that shadows
  // Car.prototype.cylinders_
  this.cylinders_ = cylinders;
};

/**
 * Gets the number of cylinders in the engine.
 * @return {number} The number of cylinders.
 */
Car.prototype.getCylinders = function() {
  return this.cylinders_;
};

В следующем примере показано, как установка свойства экземпляра затеняет свойство прототипа.

var myCar = new Car("1HGCM82633A004352");
alert(myCar.getCylinders()); // Alerts 4.

myCar.setCylinders(6);
alert(myCar.getCylinders()); // Alerts 6;

// Delete the instance property and let the prototype property
// "shine through".
delete myCar.cylinders_;
alert(myCar.getCylinders()); // Alerts 4;


Если тип свойства является изменяемым, например Array или Object, то в большинстве случаев вы не захотите использовать один и тот же экземпляр изменяемого свойства между экземплярами класса. Следовательно, изменяемые свойства чаще определяются в конструкторе, а не в прототипе.

Можно ли инициализировать свойства null?

В библиотеке замыканий есть много примеров, где свойства инициализируются значением null.. Однако лучше по возможности инициализировать переменные полезными значениями по умолчанию, например установить количество цилиндров по умолчанию равным 4, как в приведенном выше примере.

person Christopher Peisert    schedule 31.08.2012

Я также подозреваю, что это для оптимизации для двигателя V8, а также для компилятора закрытия. Если все объекты имеют одинаковые свойства, движок V8 кэширует классоподобный экземпляр (доклад IO2012). Объявляя все в прототипе, все экземпляры объектов имеют упорядоченные одинаковые свойства. Или, может быть, они просто хотят иметь четкие стили. :-)

person Kyaw Tun    schedule 04.09.2012