Multiple prototypical inheritance in Javascript -
i have 2 base classes, parentclass1
, parentclass2
. want multiple prototypical inheritance childclass
.
with single parent class, had code follows.
var parentclass = function() { }; parentclass.prototype.greetuser = function(name) { console.log('hi. hello,', name); }; var childclass = function(name) { this.greetuser(name); }; childclass.prototype = object.create(parentclass.prototype); var obj = new childclass('john'); // hi. hello, john
and when have inherit 2 parent classes, tried following code.
var parentclass1 = function() { }; parentclass1.prototype.greetuser = function(name) { console.log('hi. hello,', name); }; var parentclass2 = function() { }; parentclass2.prototype.askuser = function(name) { console.log('hey, how you,', name); }; var childclass = function(name) { this.askuser(name); this.greetuser(name); }; childclass.prototype = object.create(parentclass1.prototype); childclass.prototype = object.create(parentclass2.prototype); var obj = new childclass('john'); // error.
but seems like, accept last mentioned object.create()
.
so later, tried switching second object.create()
object.assign()
, works fine.
childclass.prototype = object.create(parentclass1.prototype); childclass.prototype = object.assign(childclass.prototype, parentclass2.prototype);
but concern object.assign()
doing a clone. right way it? or there better alternatives?
sorry making question, lengthy. in advance.
it not useful 2 assignments prototype
property, last 1 overwrite first. can this, since object.assign
accepts more arguments:
object.assign(childclass.prototype, parentclass1.prototype, parentclass2.prototype);
note object.assign
performs shallow copy. copy has made sure: need prototype object different both other prototypes: union of both. inevitably need somehow copy members of parent prototypes target prototype object.
some caveats:
1. object.assign
makes shallow copy
since object.assign
performs shallow copy, might cases interfere parent prototype. might want or not want.
example:
var parentclass1 = function() { }; parentclass1.prototype.userlist = []; parentclass1.prototype.adduser = function(name) { this.userlist.push(name); }; var parentclass2 = function() { }; parentclass2.prototype.askuser = function(name) { console.log('hey, how you,', name); }; var childclass = function(name) { this.askuser(name); }; object.assign(childclass.prototype, parentclass1.prototype, parentclass2.prototype); var p = new parentclass1('parent'); var obj = new childclass('john'); obj.adduser('tim'); // added child, console.log(p.userlist); // parent has tim...
2. object.assign
copies enumerable properties
this means in cases not properties had hoped for. wanted inherit array.prototype
, want child object have length
property, since not enumerable, not object.assign
:
var parentclass2 = function() { }; parentclass2.prototype.askuser = function(name) { console.log('hey, how you,', name); }; var childclass = function(name) { this.askuser(name); }; object.assign(childclass.prototype, array.prototype, parentclass2.prototype); var obj = new childclass('john'); console.log(obj.length); // undefined console.log(array.prototype.length); // 0
3. object.assign
executes getters
object.assign
cannot copy getters. instead executes them retrieve value copy. executing code on parent prototype may have effects (by design of getter) on state of parent prototype. might undesired behaviour in context of copy.
secondly, value of getter can result of calculation , state of object, returning different values each time referenced. object.assign
reference once, , create property has single value. see effect in example:
var parentclass1 = function() { }; // define getter on prototype returns // random number between 0 , 999, every time referenced: object.defineproperty(parentclass1.prototype, 'randomnumber', { get: function() { return math.round(math.random() * 1000); }, enumerable: true }); var parentclass2 = function() {}; parentclass2.prototype.askuser = function(name) { console.log('hey, how you,', name); }; var childclass = function(name) { this.askuser(name); }; object.assign(childclass.prototype, parentclass1.prototype, parentclass2.prototype); var p = new parentclass1('parent'); var obj = new childclass('john'); console.log('different:'); console.log(p.randomnumber); console.log(p.randomnumber); console.log(p.randomnumber); console.log('always same:'); console.log(obj.randomnumber); console.log(obj.randomnumber); console.log(obj.randomnumber);
.as-console-wrapper { max-height: 100% !important; top: 0; }
further reading
the concept of combining multiple prototypes new 1 coined "mixin". here related q&a:
- how use mixins in javascript
- javascript mixins when using module pattern
- how add mixins es6 javascript classes?
- what's difference between mixin() , extend() in javascript libraries
see factory composition.
Comments
Post a Comment