I am learning OOP in JavaScript and have gone through various posts on the same. It has come to my knowledge that Douglas Crockford prescribes a pure prototypal approach to inheritance as opposed to the classical approach.
The following code taken from here implements Crockford's method:
var superInstance = {
member1: 'superMember1',
member2: 'superMember2'
};
var subInstance = Object.create(superInstance);
subInstance.member3 = 'subMember3';
I understand that Crockford's approach does away with constructor functions (correct me if I am wrong). Does this mean that the only way to initialize object members with this approach is by using object literals as shown in above code? Also, how do I implement parasitic inheritance with this approach to allow shared members, private variables and non-scalar values in the parent class (refer this post)?
Crockford mentions "maker functions" in his article, but does not give any example code for it. It would be great if someone could demonstrate parasitic inheritance using Crockford's pure prototypal approach.
Thanks.
Misunderstanding about prototypal inheritance arise from the problem that in contrary to classical inheritance base constructor is not called to instantiate base object. Setting prototype to base object is not equivalent to classical inheritance, because prototype is shared among instances. As described in detail by Jimmy Breck-McKye. So to achieve parasitic inheritance you will have to follow two rules.
The latter can be achieved to one's taste using
Object.create
or assigning instance of base object directly to prototype. Given thatBase
is a constructor function, code for inheritance will be like belowWay #1
We will use defined constructor in the following manner
Pay attention to the missing
successorMethod
defined viaSuccessor.prototype
. This happened because we've overridden__proto__
property of the object.Way #2
Another way to override the
__proto__
property is to callObject.create
. However this function returns a new object and thus we will have to override the object that is returned bySuccessor
constructorLet's examine usage of this approach in detail:
Resulting behaviour is pretty much the same. Pay attention to the missing
neverShowMember
although it was defined forthis
within constructor. It may be source of mistakes.Way #3
Yet another way to inherit is not to mess around with proto chains. This approach is described in Jimmy Breck-McKye's article. I will skip detailed comments which were provided previously and will focus on changes
You see that schema became flat. As an obvious conclusion you can't access base members if you override them. So if inside
Successor
we defineThe instance (
child
) will lose access tobaseIntance.baseMember
which equals "I am the parent". In contrary to previous approaches when it would be accessible viachild.__proto__.baseMember
. But I believe this is not a common scenario when developing in javascript and should covered under another question.Note that in all cases members defined in
Successor.prototype
are lost. You should take care of copying them manually inSuccessor
constructor.Conclusion
I hope this description was clear enough to understand that
CraCrockford'sobject
functionalways requires a new instance passed as parameter
o
to achieve parasitic inheritance. Thus it's usage should look like belowSame applies to the code from OP. To follow parasitic inheritance
superInstance
should be a new instance each time it is passed toObject.create
. Thus it should be a factory functionor a constructor
Hope this helps