I want to inherit all the methods from source classes into my main target class/function. I kind of did something, but I wonder if there are better or gentler ways to do this.
The idea is that I can keep good readability and separate methods in groups (files) so I know what belongs where.
P.S. Sorry for my bad english
Here's how I did it:
function Main(){
const self = this
self.name = 'Main'
self.speak = () => {
console.log(`called in class Main by class ${this.name}`)
}
}
class A{
//fake variables for IDE autofill
//no constructor needed
speakA(){
console.log(`called in class A by class ${this.name}`)
}
}
class B{
speakB(){
console.log(`called in class B by class ${this.name}`)
}
}
class C{
speakC(){
console.log(`called in class C by class ${this.name}`)
}
}
;(function assignOFunctionsToObject(target, ...sources){
sources.forEach(source => {
Object.getOwnPropertyNames(source.prototype).forEach(name => {
if(typeof source.prototype[name] === "function") {
target.prototype[name] = source.prototype[name]
}
})
})
})(Main,
A, B, C)
let main = new Main()
main.speak()
main.speakA()
main.speakB()
main.speakC()
Implementing utility functions within and across different modules one could at least choose 3 different approaches ...
Write a function based mixin which is a single function with (this
aware) methods bound to the function's this
context.
apply
the imported mixin to whichever object is in need of the mixin's methods.Write an object based mixin which is a single object with (this
aware) methods.
assign
the imported mixin to whichever object is in need of the mixin's methods.Write and export (this
aware) functions.
assign
the latter to whichever object is in need of the just created mixin's methods.// module ... function_based_utility_methods_mixin_A.js
//
function speakA() {
console.log(`called as 'speakA' by instance of type '${ this.type }'`);
}
function speakAA() {
console.log(`called as 'speakAA' by instance of type '${ this.type }'`);
}
/* export default */function withUtilityMethods_A() {
this.speakA = speakA;
this.speakAA = speakAA;
}
// module ... object_based_utility_methods_mixin_B.js
//
function speakB() {
console.log(`called as 'speakB' by instance of type '${ this.type }'`);
}
function speakBB() {
console.log(`called as 'speakBB' by instance of type '${ this.type }'`);
}
/* export default */const utilityMethods_B = {
speakB,
speakBB,
}
// module ... utility_methods_C.js
//
/* export */function speakC() {
console.log(`called as 'speakC' by instance of type '${ this.type }'`);
}
/* export */function speakCC() {
console.log(`called as 'speakCC' by instance of type '${ this.type }'`);
}
// module ... main.js
// import withUtilityMethods_A from 'function_based_utility_methods_mixin_A.js';
// import utilityMethods_B from 'object_based_utility_methods_mixin_B.js';
// import { speakC, speakCC } from 'utility_methods_C.js';
function Main () {
this.type = 'main';
this.speak = () => {
console.log(`called as 'speak' by instance of type '${ this.type }'`);
};
}
// option 1 ...
// - APPLY a function based mixin to the
// `Main` constructor function's prototype.
withUtilityMethods_A.call(Main.prototype);
// option 2 ...
// - ASSIGN an object based mixin to the
// `Main` constructor function's prototype.
Object.assign(Main.prototype, utilityMethods_B);
// option 3 ...
// - ASSIGN an ad-hoc created object based mixin
// to the `Main` constructor function's prototype.
Object.assign(Main.prototype, { speakC, speakCC });
const main = new Main();
main.speak();
main.speakA();
main.speakAA();
main.speakB();
main.speakBB();
main.speakC();
main.speakCC();
console.log({
mainPrototype: Main.prototype
});
.as-console-wrapper { min-height: 100%!important; top: 0; }