A seemless way to organize multi inheritance.
Caution this function uses ES6 Proxies, Sets and Symbols. Use Ring.js or similar libaries, if you want an ES5 approach.
You should always prefer other patterns like decorators or annotions if you can, because javascript does not support this for good reasons:
- must have the same arguments signiture
- hard to isolate instances
- overhead
Uses ProxyScope to reflects all changes to prototype of all mixins.
Allows the use of instanceof by overwriting all Subclass[Symbols.hasInstance].
Caution: this will make instanceof more expensive.
constEventEmitter=require('events');constlisten=["on","once"];classArrayEmitterextendsProxyClass.hasInstance(Array,EventEmitter){constructor(options){let{ data }=options;super(...data);listen.forEach((property)=>{lettype=options[property];if(type){for(leteventintype){letlisteners=type[event];if(!Array.isArray(listeners)){listeners=[listeners];}listeners.forEach((listener)=>{this[property](event,listener)});}}});this.emit("push",data);}push(...args){super.push(...args);this.emit("push",args);}}letinput=["fubar","haha"];letae=newArrayEmitter({data : input,on : {push(...args){console.log("every push",args);}},once : {push(...args){console.log("inital push",args);}}});ae.push("last");//will be truenainstanceofArrayEmitter;nainstanceofArray;nainstanceofEventEmitter;Deep Classes
classA{constructor(){this.aProp=true;this.shared="sharedA";}getisA(){returntrue;}getsharedA(){returnthis.shared;}sharedAFn(){returnthis.shared;}}classB{getisB(){returntrue;}}classCextendsProxyClass.hasInstance(A,B){getisC(){returntrue;}}classD{getisD(){returntrue;}}classEextendsProxyClass.hasInstance(C,D){constructor(){super();this.eProp=true;}getisE(){returntrue;}};//You can also inline your classvarF=ProxyClass.hasInstance(class{constructor(someArg){this.someArg=someArg;this.fProp=true;}getisF(){returntrue;}},E);vare=newE();//all of this will return trueeinstanceofObject;einstanceofA;einstanceofB;einstanceofC;einstanceofD;einstanceofE;e.isA;e.isB;e.isC;e.isD;e.isE;e.aProp;e.eProp;varf=newF("fubar");//same as e plusfinstanceofF;f.isF;f.fProp;f.someArg=="fubar";All class member function will get called with their own isolated context.
expect(e.shared).toEqual("sharedE");expect(e.sharedA).toEqual("sharedA");expect(e.sharedAFn()).toEqual("sharedA");ISC