Reputation: 634
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
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
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
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