I\'m creating two objects (Inherits), both inherit from Base. The second object\'s property assignment overrides the value in the first object.
Any thoughts? How to
Base
class constructor is called once and only once.this
object across instances because those methods are created within the constructor (which was called only once).Function.prototype
) if you plan on working alongside JavaScript that you do not own.Please pay special attention to the inherits
function and the ParentClass.call(this, title);
line.
Constructors to look for are ParentClass
and ChildClass
/**
* Allows a child constructor to safely inherit the parent constructors prototype chain.
* @type {Function}
* @param {!Function} childConstructor
* @param {!Function} parentConstructor
*/
function inherits(childConstructor, parentConstructor){
var TempConstructor = function(){};
TempConstructor.prototype = parentConstructor.prototype; // Inherit parent prototype chain
childConstructor.prototype = new TempConstructor(); // Create buffer object to prevent assignments directly to parent prototype reference.
childConstructor.prototype.constructor = childConstructor; // Reset the constructor property back the the child constructor
};
//////////////////////////////////////
/** @constructor */
function ParentClass(title) {
this.setTitle(title);
var randId_ = Math.random();
/** @return {number} */
this.getPrivlegedRandId = function()
{return randId_;};
};
/** @return {string} */
ParentClass.prototype.getTitle = function()
{return this.title_;};
/** @param {string} value */
ParentClass.prototype.setTitle = function(value)
{this.title_ = value;};
//////////////////////////////////////
/**
* @constructor
* @param {string} title
* @param {string} name
*/
ChildClass = function (name, title) {
ParentClass.call(this, title); // Call the parent class constructor with the required arguments
this.setName(name);
}
inherits(ChildClass, ParentClass); // Inherit the parent class prototype chain.
/** @return {string} */
ChildClass.prototype.getName = function()
{return this.name_;};
/** @param {string} value */
ChildClass.prototype.setName = function(value)
{this.name_ = value;};
For those who are curious why that works vs simply memorizing it the inherits
function.
When a property is not found at the instance level, JavaScript will try to resolve the missing property by searching through the instance constructors prototype chain. If the property is not found in the first prototype object, it will search the parent prototype object and so on all the way up to Object.prototype
. If it can't find it within Object.prototype
then an error will be thrown.
// Bad
var ChildConstructor = function(arg1, arg2, arg3){
var that = new ParentConstructor(this, arg1, arg2, arg3);
that.getArg1 = function(){return arg1};
return that;
}
Any varible that is created using new ChildConstructor
will return an instance of ParentConstructor
.
The ChildConstructor.prototype
will be not be used.
// Good
var ChildConstructor = function(arg1, arg2, arg3){
ParentConstructor.call(this, arg1, arg2, arg3);
}
Now constructor and the parent constructor is called appropriately. However, only methods defined within the constructor(s) will exist. Properties on the parent prototypes will not be used because they have not yet been linked to the child constructors prototype.
// Bad
ChildConstructor.prototype = new ParentConstructor();
The parent constructor will either be called only once or one too many times depending on whether or not ParentConstructor.call(this)
is used.
// Bad
ChildConstructor.prototype = ParentConstructor.prototype;
Though this technically works, any assignments to ChildConstructor.prototype
will also be assigned to ParentConstructor.prototype
because Objects are passed by reference and not by copy.
// Almost there
var TempConstructor = function(){};
TempConstructor.prototype = ParentConstructor.prototype;
ChildConstructor.prototype = new TempConstructor();
This allows you to assign properties to ChildConstructor.prototype
because it is an instance of a temporary anonymous function.
Properties that are not found on the instance of TempConstructor
will then check it's prototype chain for the property, so you have successfully inherited the parent prototype. The only problem is that ChildConstructor.prototype.constructor
is now pointing to TempConstructor
.
// Good
var TempConstructor = function(){};
TempConstructor.prototype = ParentConstructor.prototype;
ChildConstructor.prototype = new TempConstructor();
ChildConstructor.prototype.constructor = ChildConstructor;
var ParentConstructor = function(){
};
var ChildConstructor = function(){
ParentConstructor.call(this)
};
var TempConstructor = function(){};
TempConstructor.prototype = ParentConstructor.prototype;
ChildConstructor.prototype = new TempConstructor();
ChildConstructor.prototype.constructor = ChildConstructor;
You've successfully inherited from the parent class! Let's see if we can do better.
function inherits(childConstructor, parentConstructor){
var TempConstructor = function(){};
TempConstructor.prototype = parentConstructor.prototype; // Inherit parent prototype chain
childConstructor.prototype = new TempConstructor(); // Create buffer object to prevent assignments directly to parent prototype reference.
childConstructor.prototype.constructor = childConstructor; // Reset the constructor property back the the child constructor (currently set to TempConstructor )
};
var ParentConstructor = function(){
};
var ChildConstructor = function(){
ParentConstructor.call(this)
};
inherits(ChildConstructor, ParentConstructor);