I have a Java background and I have been experimenting with JavaScript inheritance lately. I started writing some objects and after reading some examples I found the code style which suits me the most.
Here is what I have:
var Class = function() {};
Class.extend = function(p_constructor) {
var Superclass = this;
// the following line confuses me
p_constructor.prototype = Object.create(Superclass.prototype);
p_constructor.prototype.constructor = p_constructor;
p_constructor.extend = Superclass.extend;
return p_constructor;
};
So now when I wish to define an object which extends Class I just type:
var Person = Class.extend(function(p_firstName, p_lastName) {
this.firstName = p_firstName;
this.lastName = p_lastName;
});
and the following will be true:
var p = new Person('john', 'smith');
p instanceof Person; // true
p instanceof Class; // true
I only have trouble understanding what's the effective difference between the following lines in the Class.extend
function:
/* 1) */ p_constructor.prototype = new Superclass();
/* 2) */ p_constructor.prototype = Superclass.prototype;
/* 3) */ p_constructor.prototype = Object.create(Superclass.prototype);
/* 4) */ p_constructor.prototype = Object.create(Superclass);
I do realize that using the 1st line is not very wise if some super constructors throw errors, but what's exactly the difference between lines 2, 3 and 4?
To answer my own question:
/* 1) */ p_constructor.prototype = new Superclass();
Like I said, it's not very wise to use this because it actually creates the whole Superclass object. The whole point of prototypal inheritance is to share the prototype objects so redundant function (and sometimes object) definitions can be avoided.
/* 2) */ p_constructor.prototype = Superclass.prototype;
This would be OK if you could be sure that the constructor's prototype would never be modified by third party. Suppose somebody who uses your class wants to add additional functionality to its prototype. Changing the p_constructor's prototype would directly influence the superclass' prototype and could introduce errors in the superclass' behaviour. So the next line of code is used instead:
/* 3) */ p_constructor.prototype = Object.create(Superclass.prototype);
This creates a new object (instance) whose prototype (actually the __proto__
variable) is set to Superclass' prototype. Any changes to p_constructor.prototype
now makes no changes to the Superclass' behaviour.
/* 4) */ p_constructor.prototype = Object.create(Superclass);
The upper line works, but makes no sense because it only sets the prototype to the Superclass' constructor.
Also, the following line was confusing to me as well:
p_constructor.prototype.constructor = p_constructor;
It makes no difference in the p_constructor's behaviour, it only makes the reference to the constructor available in the instantiated object. A neat trick is to add the superclass to the prototype as well:
p_constructor.prototype.superclass = Superclass;
And then the following piece of code would work:
function Constructor(p_params) {
// call constructor of the superclass
this.superclass(p_params);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With