5

下面的示例显示了一个扩展 goog.ui.Component 的类。

类的属性应该在构造函数之外定义,如下所示,还是应该只在构造函数中内联定义?

可以将属性初始化为null吗?

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);
4

2 回答 2

3

闭包库实现了具有在原型上以及在构造函数中定义的属性的类。除了研究闭包库源代码之外,这里还有一些在决定是在原型上还是在构造函数中定义属性时要考虑的问题。

类的每个实例的属性是否唯一?

每个实例唯一的属性(例如汽车的 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,如上例所示。

于 2012-08-31T19:48:18.920 回答
0

我还怀疑它是为了优化 V8 引擎以及闭包编译器。如果所有对象都具有相同的属性,V8 引擎会缓存类实例(IO2012 talk)。通过在原型中声明所有内容,所有对象实例都具有有序的相同属性。或者他们可能只是想拥有清晰的风格。:-)

于 2012-09-04T13:16:11.840 回答