1

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
Serhii Holinei
  • 5,758
  • 2
  • 32
  • 46
  • 1
    Possible duplicate of [How to check if function exists in JavaScript?](https://stackoverflow.com/questions/1042138/how-to-check-if-function-exists-in-javascript) – Liam Oct 19 '18 at 14:35
  • 1
    @Liam That isn't remotely close to a dupe for this. – Blue Oct 19 '18 at 14:44
  • 1
    @Liam Linked duplicate asks the general question, "Does this method exist _at all_?" - The question OP is asking is, "How do I confirm A is a method of class B?". – Lewis Oct 19 '18 at 14:44
  • It should return true if it's specifically a method of the specific instance of A? or generally a method of class A? – Reuven Chacha Oct 19 '18 at 14:53
  • @ReuvenChacha `generally a method of class A` – Serhii Holinei Oct 19 '18 at 14:54

4 Answers4

3

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
Ori Drori
  • 183,571
  • 29
  • 224
  • 209
0

    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.

Matthi
  • 1,073
  • 8
  • 19
0

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] )
}
Rajib Chy
  • 800
  • 10
  • 22
0

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;
        }
    }
    
Reuven Chacha
  • 879
  • 8
  • 20