下面的示例显示了一个扩展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);
答案 0 :(得分:3)
Closure Library实现具有在原型和构造函数中定义的属性的类。除了研究Closure Library源代码之外,在决定是在原型上还是在构造函数中定义属性时,还需要考虑以下问题。
每个实例的唯一属性(例如汽车的VIN编号)不应在实例之间共享,因此在构造函数中定义,而不是在原型上定义。
/**
* A car.
* @param {string} vin The Vehicle Identification Number.
* @constructor
*/
Car = function(vin) {
/**
* The Vehicle Identification Number.
* @type {string}
* @private
*/
this.vin_ = vin;
};
由于可以在实例之间安全地共享不可变属性类型,因此应该在原型上定义它们。如果实例需要覆盖共享的默认值,则可以添加实例属性以隐藏同名的prototype属性。
/**
* 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_;
};
以下示例说明了如何设置instance属性隐藏prototype属性。
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
可以吗?
Closure Library中有许多示例,其中属性初始化为null.
但是,最好在可能的情况下将变量初始化为有用的默认值,例如将默认柱面数设置为4,如示例中所示以上。
答案 1 :(得分:0)
我还怀疑它是针对V8引擎以及闭包编译器进行优化的。如果所有对象具有相同的属性,则V8引擎缓存类似于类的实例(IO2012 talk)。通过声明原型中的所有内容,所有对象实例都具有有序相同的属性。或者他们可能只想拥有清晰的风格。 :-)