Nikhil Goyal
Nikhil Goyal

Reputation: 1973

Get function reference of class (not object)

I have a code where a function is used to modify the existing functions and return a new function reference. I want that function to be applied to specific methods of a class. My current code is

function modifyMethod(func) {
  return function() {
    console.log('working');
    return func.apply(this, arguments);
  };
}

function modifyClassMethods(ClassName, methodArray) {
  // The code goes here

  return ClassName;
}

class Temp {
  hi() {
    console.log("hi method");
  }
}

Temp = modifyClassMethods(Temp, ["hi"]);
const temp = new Temp();
// This should print
//
// working
// hi method
temp.hi();

When I try to call the method modifyMethod with Temp.hi, func is undefined. If I create an object and then modify the method, then the new method will be applied only to the method of that particular object and not to all the objects of that particular class.

Note that this is just an example. I want to apply this modification to the methods of multiple classes. So, I can't generalize the method names also. Any code snippet for the modifyClassMethods will be helpful.

Upvotes: 1

Views: 616

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1074266

The methods defined with method syntax in the body of a class construct that aren't marked static are prototype methods and so they're on Temp.prototype, not Temp itself. So that's where you'd update them:

Temp.prototype.hi = modifyMethod(Temp.prototype.hi);

Only static methods end up on Temp itself.

You may see other functions created within the class body using the class fields proposal's syntax:

class Temp {
    hi = () => {
        //
    };
}

Those are instance methods. They're created by the constructor, and re-created for each instance, roughly as though they'd been written like this:¹

class Temp {
    constructor() {
        this.hi = () => {
            //
        };
    }
}

You can't wrap those until/unless an instance is created, as they're instance-specific.

So to wrap up, consider:

class Temp {
    static staticMethod() {
        // ...
    }
    prototypeMethod() {
        // ...
    }
    instanceMethod = () => {
        // ...
    };
    constructor() {
        this.anotherInstanceMethod = () => {
            // ...
        };
        this.yetAnotherInstanceMethod = function {
            // ...
        };
    }
}

That class shows the three types of methods:

  • Static Methods, such as staticMethod, which you'll find on Temp (e.g., Temp.staticMethod);
  • Prototype Methods, such as prototypeMethod, which you'll find on Temp.prototype (e.g., Temp.prototype.prototypeMethod); and
  • Instance Methods, such as instanceMethod, anotherInstanceMethod, and yetAnotherInstanceMethod, which you'll find on the instances themselves, if/when any instances are created

¹ Technically, they're created as though with Object.defineProperty like this:

class Temp {
    constructor() {
        Object.defineProperty(this, "hi", {
            value: () => {
                //
            },
            writable: true,
            configurable: true,
            enumerable: true
        });
    }
}

...not via simple assignment. I used simple assignment in the example to keep it...simple. :-)

Upvotes: 4

Related Questions