Jeffrey Delos Santos
Jeffrey Delos Santos

Reputation: 77

Extend class to a multiple class instances Javascript

I have UserModel class which has static methods, and I want to extend or inherit to multiple class instances.

UserModel.js

const tableName = "Users";
const primaryKey = "UserID";
const secondaryTables = [{ id: "RoleID", name: "Roles", relation: " INNER JOIN " }];
const getterModel = new GettersModel(tableName, primaryKey, secondaryTables);
const deleteModel = new DeleteModel(tableName, primaryKey);

class UserModel {

    constructor() {

    }

    static async insertUser({ username, password, roleId }) {
        ...
    }
    ...
}
Object.setPrototypeOf(UserModel, getterModel);
Object.setPrototypeOf(UserModel, deleteModel);

DeleteModel.js

class DeleteModel {
    constructor(tableName, primaryKey) {
        this.tableName = tableName;
        this.primaryKey = primaryKey;

    }
     async deleteRow(id) {

        try {
            const result = await mysql_conn.delete(this.tableName, `where 
                                  ${this.primaryKey}=?`, [id]);
            return result;

        } catch (err) {
            console.error(err);
            return false;
        }
    }

}

UserService.js

async function deleteUser(userID) {

        let ret = await UserModel.deleteRow(userID);

        if (ret == false) {
            return { status: false }
        } else {
            return { status: true }
        }

}

But the problem is GettersModel gets replaced by the prototype of DeleteModel when setting this:

Object.setPrototypeOf(UserModel, getterModel);
Object.setPrototypeOf(UserModel, deleteModel);

And also, there's a warning in MDN website about .setPrototypeOf():

From MDN

Warning: Changing the [[Prototype]] of an object is, by the nature of how modern JavaScript engines optimize property accesses, currently a very slow operation in every browser and JavaScript engine. In addition, the effects of altering inheritance are subtle and far-flung, and are not limited to simply the time spent in the Object.setPrototypeOf(...) statement, but may extend to any code that has access to any object whose [[Prototype]] has been altered.

Because this feature is a part of the language, it is still the burden on engine developers to implement that feature performantly (ideally). Until engine developers address this issue, if you are concerned about performance, you should avoid setting the [[Prototype]] of an object. Instead, create a new object with the desired [[Prototype]] using Object.create().

So how can I do this? Thanks

Upvotes: 0

Views: 132

Answers (1)

Bergi
Bergi

Reputation: 664764

You should not use inheritance here. The UserModel class should use the deleteModel instance.

To expose UserModel.deleteRow, you can use

class UserModel {
    constructor() {…}
    static async insertUser(…) { … }
    
    static deleteRow = deleteModel.deleteRow.bind(deleteModel)
}

or

class UserModel {
    constructor() {…}
    static async insertUser(…) { … }
}
UserModel.deleteRow = deleteModel.deleteRow.bind(deleteModel);

However, I would suggest that you should not expose a deleteRow method on your UserModel - what is a row? You should instead write

class UserModel {
    constructor() {…}
    static async insertUser(…) { … }
    
    static async deleteUser(userID) {
        return {status: await deleteModel.deleteRow(userID)};
    }
}

Upvotes: 1

Related Questions