Serhii Holinei
Serhii Holinei

Reputation: 5864

Check if a function is a method of a class?

Is there a way to determine if a function is a method of a certain class?

I have a class A with a method doesMethodBelongHere, that takes a function as an argument method. I want to determine that method is an actual method of A.

class A {
  methodA() {
    console.log('method of A');
  }
  
  doesMethodBelongHere(method) {
    // it should return true if `method` argument is a method of A
    return Object.values(this).includes(method);
  }
}

const a = new A(); 
console.log(a.doesMethodBelongHere(a.methodA)); // should return true

Upvotes: 1

Views: 735

Answers (4)

Ori Drori
Ori Drori

Reputation: 191986

You can use Object.getPrototypeOf() to get the prototype. Then iterate the prototype properties using for...of, and Object.getOwnPropertyNames(). If the method is equal to one of the methods on the prototype return true:

class A {
  methodA() {
    console.log('method of A');
  }

  doesMethodBelongHere(method) {
    // get the prototype
    const proto = Object.getPrototypeOf(this);
    
    // iterate the prototype properties, and if one them is equal to the method's reference, return true
    for(const m of Object.getOwnPropertyNames(proto)) {
      const prop = proto[m];
      if(typeof(prop) === 'function' && prop === method) return true;
    }
    
    return false;
  }
}

const a = new A();
Object.assign(a, { anotherMethod() {} }); 
a.anotherMethod2 = () => {};

console.log(a.doesMethodBelongHere(a.methodA)); // should return true

console.log(a.doesMethodBelongHere(a.anotherMethod)); // should return false

console.log(a.doesMethodBelongHere(a.anotherMethod2)); // should return false

Extended classes:

This solution will also handle methods that comes from an extended class:

class A {
  methodA() {
    console.log('method of A');
  }

  doesMethodBelongHere(method) {
    let proto = this;
    
    // iterate the prototypes chain
    while (proto = Object.getPrototypeOf(proto), proto && proto !== Object) {
      // iterate the prototype properties, and if one them is equal to the method's reference, return true
      for (const m of Object.getOwnPropertyNames(proto)) {
        const prop = proto[m];
        if (typeof(prop) === 'function' && prop === method) return true;
      }
    }

    return false;
  }
}

class B extends A {}

class C extends B {}

const c = new C();
Object.assign(c, {
  anotherMethod() {}
});

c.anotherMethod2 = () => {};

console.log(c.doesMethodBelongHere(c.methodA)); // should return true

console.log(c.doesMethodBelongHere(c.anotherMethod)); // should return false

console.log(c.doesMethodBelongHere(c.anotherMethod2)); // should return false

Upvotes: 3

Reuven Chacha
Reuven Chacha

Reputation: 889

I'd suggest to use the following implementation:

  1. Use Object.getOwnPropertyNames on the constructor prototype (the same accessing A.prototype, but in a more generic approach) in order to iterate class methods.
  2. Get method name using method.name
  3. Using Array.some, find whether (1) includes the name of the given method.

    class A {
    
        constructor() {
            this.a = 2;
            this.bb = 3;
        }
        methodA() {
            console.log('method of A');
        }
    
        doesMethodBelongHere(method) {
            // it should return true if `method` argument is a method of A
            return this.constructor.prototype[method.name] === method;
        }
    }
    

Upvotes: 0

Rajib Chy
Rajib Chy

Reputation: 880

You can use typeof operator

let isfn = "function" === typeof ( a.methodA );//isfn should be true
isfn = "function" === typeof ( a["methodA"] );//isfn should be true
isfn = "function" === typeof ( a["methodAX"] );//isfn should be false

Edit

doesMethodBelongHere( method ) {
    return  "function" === typeof ( this[method.name] )
}

Upvotes: 0

Matthi
Matthi

Reputation: 1063

    class A {
      constructor() {
        this.methodA = this.methodA.bind(this);
        this.doesMethodBelongHere = this.doesMethodBelongHere.bind(this);
      }
    	methodA() {
        console.log('method of A');
      }
      
      doesMethodBelongHere(method) {
        // it should return true if `method` argument is a method of A
        return Object.values(this).includes(method);
      }
    }

    const a = new A(); 
    console.log(a.doesMethodBelongHere(a.methodA)); // should return true

This was not bound to your class in your doesMethodBelongHere.

Upvotes: 0

Related Questions