xx yy
xx yy

Reputation: 634

JavaScript class: (instanceof this)

I want to check if an object is an instance of the current class it works fine from outside the class, but gives error if I called it from inside the class

class test {

  check(obj) {
    return (obj instanceof this) //error: this is not a function

  }
}


const obj = new test()

console.log(obj instanceof test) //true
console.log(new test().check(obj)) //ERROR

Solving:

method #1: (by: @CertainPerformance ) we cannot use: return obj instanceof this,

because (this) is an object (i.e: obj instanceof OBJECT),

so we can use the constractor object:

return obj instanceof this.constructor

method #2: (by: @Matías Fidemraizer )

   return Object.getPrototypeOf(this).isPrototypeOf () //using this->better 

   //or: className.prototype.isPrototypeOf (obj) 
      //if you know the class name and there is no intent to change it later

method #3: (by: @Thomas ) make the function "check" static

static check(obj) {
    // now `this` points to the right object, the class/object on which it is called,        
    return obj instanceof this;
  }

Upvotes: 0

Views: 2103

Answers (3)

Thomas
Thomas

Reputation: 12657

imo. check doesn't belong where it is right now. It makes no sense to write this functionality as an instance method; better would be a static method:

class Test {
  // check is now a static method
  static check(obj) {
    // and now `this` points to the right object, the class/object on wich it is called, 
    // not some instance.
    return obj instanceof this;
  }
}

// extending the class Test
class Test2 extends Test {}

const obj = new Test(), obj2 = new Test2();
// Tests
[
  () => obj instanceof Test, //true
  () => Test.check(obj), //true
  () => new Test().check(obj), //ERROR: because `check` is no longer an instance method

  // Test2 has inherited static check:
  () => obj2 instanceof Test2, //true
  () => Test2.check(obj2), //true
  () => Test2.check(obj), //false, obj is no instance of Test2
  () => Test.check(obj2), //true
  () => {
    var check = Test.check;
    // ERROR, because here you call `check` with no class/object
    return check(obj);  
  }
].forEach(fn => {
  try {
    console.log("%s: %o", fn, fn());
  } catch (err) {
    console.error(err);
  }
});
.as-console-wrapper{top:0;max-height:100%!important}

Upvotes: 0

Matías Fidemraizer
Matías Fidemraizer

Reputation: 64943

instanceof is meant to test if a given instance of some given prototype giving the constructor function.

Actually, you can't check {} instanceof {}, which is what you're really doing.

This is the reason behind the fact that the first check works, the other no.

What about using Object#isPrototypeOf?

class A {
   check (x) {
       return A.prototype.isPrototypeOf (x) 
   }
}

class B extends A {}

class C {}

const a = new A ()
const b = new B ()
const c = new C ()

console.log (a.check (a))
console.log (a.check (b))
console.log (a.check (c))

Or, as @vlaz has pointed out in some comment, you might use Object.getPrototypeOf to extract the prototype from this:

class A {
   check (x) {
       return Object.getPrototypeOf(this).isPrototypeOf (x) 
   }
}

class B extends A {}

class C {}

const a = new A ()
const b = new B ()
const c = new C ()

console.log (a.check (a))
console.log (a.check (b))
console.log (a.check (c))

Upvotes: 1

CertainPerformance
CertainPerformance

Reputation: 371079

The specific error message is:

Uncaught TypeError: Right-hand side of 'instanceof' is not callable

on the line

return (obj instanceof this)

Which makes sense - the right-hand side of instanceof should be a class (or function), such as test. Something that isn't a function (like an object) can't be called, so <something> instanceof <someobject> doesn't make sense.

Try referring to the constructor of the object instead, which will point to the class (test):

return obj instanceof this.constructor

class test{
  check(obj){
    return obj instanceof this.constructor

  }
}
obj=new test()
console.log(obj instanceof test) //true
console.log(new test().check(obj)) //ERROR

Upvotes: 3

Related Questions