Currently I implement inheritance in my JavaScript libraries as follows:
parent = function() { };
parent.prototype.hello = function() { alert('parent'); };
child = function() { };
child.prototype = parent.prototype;
However, I've noticed when I override a function in a child "class's" prototype, it undesirably overrides the parent's prototype as well:
child.prototype.hello = function() { alert('child'); }
(new parent()).hello(); // alerts "child" --> undesirable
(new child()).hello(); // alerts "child" --> desirable
And if I delete something from the child's prototype
delete child.prototype.hello;
then the parent's prototype is undesirably affected. So, maybe
child.prototype = parent.prototype;
is not the best way of implementing inheritance? Instead of making child "classes" reference the parent prototype, perhaps it would make more sense to copy the parent prototype to the child prototype?
_.extend(child.prototype, parent.prototype);
child.prototype = parent.prototype;
is incorrect, for the reason you've detailed in your question.
Using _.extend
isn't want you want, either. Consider that a change in an "inherited" parent prototype property will not cause a change in the child:
// perform extension
_.extend(child.prototype, parent.prototype);
// parent later gains new property after extension
parent.prototype.parentProp = function() { alert("new"); };
(new parent()).parentProp(); // alerts "new" --> desirable
(new child()).parentProp(); // error; doesn't exist --> undesirable
You probably want child.prototype = Object.create(parent.prototype);
This says: "Store a new object in child.prototype
. This new object uses the parent.prototype
object as its own prototype." This causes real inheritance to happen, because when a child
instance wants a property, it first looks in its own properties, then in its immediate prototype (child.prototype
), and then in its prototype's prototype (parent.prototype
).
Prototype chains
When using child.prototype = parent.prototype
, the prototype chains for the instances look like:
{ child instance } ==> { only prototype }
{ parent instance } ==> { only prototype }
where only prototype
is the shared object referred to by both child.prototype
and parent.prototype
.
When using _.extend(child.prototype, parent.prototype)
, the child prototype and parent prototypes are different, but there's no direct inheritance. Changing the parent prototype doesn't change the child at all, since we merely copied the parent prototype's properties into the child prototype at one single point in time.
{ child instance } ==> { child.prototype }
{ parent instance } ==> { parent.prototype }
With child.prototype = Object.create(parent.prototype);
you actually have inheritance happening from parent to child prototype:
{ child instance } ==> { child.prototype } ==> { parent.prototype }
{ parent instance } ==> { parent.prototype }
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