sample.js







class Mid {

    a(){
        // console.log(this);
        console.log("trait a");
        super.a();
    }
    b(){
        console.log("trait a");
    }
    c(){
        console.log('trait c');
    }

    d(){
        console.log('trait d');
    }
}


class Trait {

    static getChildFuncs(staticObj){
        const proto = staticObj.prototype;
        const keys = Object.getOwnPropertyNames(proto);
        const methods = {};
        for (const key of keys){
            const param = proto[key];
            if (typeof param == typeof function(){}){
                methods[key] = param;
            }
        }
        return methods;
    }
    static getParentFuncs(staticObj){
        const proto = staticObj.prototype;
        const keys = Object.getOwnPropertyNames(proto);
        const methods = {};
        for (const key of keys){
            const param = proto[keys];
            if (typeof param == typeof function(){}){
                methods[key] = param;
            }
        }
        return methods;
    }
    static use(staticObj, traitName){
        const childFuncs = this.getChildFuncs(this);
        const traitFuncs = this.getChildFuncs(traitName);
        for (const key in traitFuncs){
            if ((childFuncs[key]??undefined)==undefined)this.prototype[key] = traitName.prototype[key]
                // function(){
                //     var parent = new SuperParent(this);
                //     traitFuncs[key].call(this);
                // };
        }
        // console.log(childFuncs);
        // console.log(traitFuncs);
        const finalFuncs = this.getChildFuncs(staticObj);
        console.log(finalFuncs);
        // const parentFuncs = getParentFuncs();
    }
}

class Parent extends Trait {

    a(){
        console.log("parent a");
    }
    b(){
        console.log("parent b");
    }


    // use(traitName){
    //     Trait.use(this,traitName);
    // }
}

class Child extends Parent {

    b(){
        console.log('child b');
        super.b();
    }
    d(){
        console.log('child d');
    }
}

Child.use(Child, Mid);

const c = new Child();

c.b(); // should yield "child b", "parent b"
c.a(); // should show "trait a", "parent a"
c.c(); // should yield "trait c"
c.d(); // should yield "child d"