'How to combine functions from many javascript classes into one object

I’ve got a quick javascript question.

Say I’ve got RootFile.js

import UserApi from './UserApi'
export default class RootFile {

  get userApi() {
    return UserApi;
  }
};

and then I got UserApi.js

import Auth from './auth';
import Profile from './profile';

const merged = {
  ...new Auth, 
  ...new Profile 
}

export default merged;

and then I got separate functionality files likeauth.js or profile.js.

auth.js

export default class Auth{
  authLog(){
    console.log("DONE");
    //Gotta find a way to run this.
  }
}

profile.js

export default class Profile{
  profileLog(){
    console.log("DONE");
    //Gotta find a way to run this.
  }
}

Now I want to be able to call:

import RootFile from './RootFile'

RootFile.userApi.profileLog();
//and
RootFile.userApi.authLog();

I can't get that to work, RootFile.userApi is a typeof object, but authLog is undefined. What am I doing wrong?



Solution 1:[1]

I don't think that use of the ... spread operator is correct. Try using Object.assign instead - it takes a target object and assigns all of the enumerable properties of other objects to it.

import Auth from './auth';
import Profile from './profile';

let merged = {};
Object.assign(merged, new Auth, new Profile);

export default merged;

Solution 2:[2]

I do not think you want to do that. The whole point of separating the logic in their respective classes is getting a more structured and better maintainable library.

I would go with composition:

export default class RootFile  {

  get userApi() {
    // Some logic here?

    // Just return a newly created api for now:
    return new UserApi;
  }
};

Do the same with UserApi:

export default class UserApi {

  get profile() {
    return new Profile;
  }
};

And use it like this:

rootFile.userApi.profile.log("etc");

Why composition?

  • This way you do not have to worry about redefinitions of functions.
  • It is faster, JavaScript engines can now optimize for your classes while this is not possible for merged constructs.

Also remember that getters are less performing than properties. I think you should consider using properties for common used members of classes

Solution 3:[3]

I did this -

import { One } from './one.js'
import { Two } from './two.js'
import { Three } from './three.js'

const MasterClazz2 = {
    ...new One(),
    ...new Two(),
    ...new Three()
}

export default MasterClazz2

Then I import like this-

import func from './combinedClazz.js'

func.oneFunc()
func.threeFunc()
func.threeFunc()
func.threeNameFunc('Sebastian')

console.log('variable: ' + func.one)
console.log('variable: ' + func.two)
console.log('variable: ' + func.three)

func. shows all the variables and functions from classes One, Two and Three in the intellisense as if they were from one class

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Jack Guy
Solution 2 Community
Solution 3 Sebastian