The example below shows a class that extends a goog.ui.Component.
Should the properties of a class be defined outside of the constructor as shown below, or should they be defined inlined in the constructor only?
Is it ok to initialize properties to 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);
The Closure Library implements classes with properties defined on the prototype as well as within the constructor function. In addition to studying the Closure Library source code, here are some questions to consider when deciding whether to define a property on the prototype or in the constructor.
Properties that are unique for each instance (such as a car's VIN number) should not be shared between instances and are therefore defined in the constructor and not on the prototype.
/**
* A car.
* @param {string} vin The Vehicle Identification Number.
* @constructor
*/
Car = function(vin) {
/**
* The Vehicle Identification Number.
* @type {string}
* @private
*/
this.vin_ = vin;
};
Since immutable property types may be safely shared between instances, they should be defined on the prototype. If an instance needs to override the shared default value, an instance property may be added that shadows the prototype property of the same name.
/**
* 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_;
};
The following example illustrates how setting the instance property shadows the prototype property.
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;
If the property type is mutable, such as Array or Object, then in most cases you would not want to share the same mutable property instance between instances of the class. Hence, mutable properties are more often defined in the constructor and not on the prototype.
Is it ok to initialize properties to
null
?
There are many examples in the Closure Library where properties are initialized to null.
However, it is better to initialize variables to useful default values when possible, such as setting the default number of cylinders to 4 as in the example above.