Reputation: 94319
function A(){}
A.prototype = "Foo bar";
new A() instanceof A;
// TypeError: Function has non-object prototype 'Foo bar' in instanceof check
As you can see, if the prototype of a constructor is not an object, it will fail and throw an error. Is there a way to make sure instanceof
will not fail?
typeof new A().constructor.prototype === "object"
and
typeof Object.getPrototypeOf(new A()) === "object"
apparently do not work.
Upvotes: 3
Views: 5613
Reputation: 147363
Perhaps not really an answer, but an interesting conclusion.
When a function is called as a constructor, if its prototype property isn't an Object, then the new instance is assigned the intrinsicDefaultProto as its [[Prototpye]]
as described in GetPrototypeFromConstructor.
In the process of creating a new instance, the intrinsicDefaultProto is passed the value of the fallbackProto, which seems to be (in Firefox at least), Object.prototype.
And since the constructor property of Object.prototype is Object, then testing whether the instance's constructor property references the candidate object won't work either.
function Foo(){}
Foo.prototype = 'A';
var foo = new Foo();
// foo inherits directly from Object.prototype, not Foo
console.log(Object.getPrototypeOf(foo) == Object.prototype) // true
// foo also inherits constructor property from Object.prototype
console.log(foo.constructor == Object) // true
So a circumstance in which instanceof fails likely points to more serious issues in the program design or implementation. Hiding such errors seems to not be a good idea (unless the intention is to leave traps within the code for future maintainers to discover).
Upvotes: 1
Reputation: 780842
Use try/catch
to catch the error;
function isItA(obj) {
try {
return obj instanceof A;
} catch (e) {
return false; //
}
}
function A() {}
A.prototype = "Foo bar";
function B() {}
B.prototype = "Baz Quux";
console.log(isItA(new A()));
console.log(isItA(new B()));
Upvotes: 1
Reputation: 664366
The error says A.prototype
needs to be an object, so you should check for that:
function isObject(x) {
return x != null && (typeof x == "object" || typeof x == "function");
}
but isObject(A.prototype)
is not all you can do to assert an instanceof
call won't throw. Going by the spec, you should test
function allowsInstanceCheck(C) {
try {
if (!isObject(C)) return false;
var m = C[Symbol.hasInstance];
if (m != null) return typeof m == "function";
if (typeof C != "function") return false;
return isObject(C.prototype);
} catch (e) {
// any of the property accesses threw
return false;
}
}
Upvotes: 3