Reputation: 4386
I know that one should not use __proto__
directly in the code, but just out of curiosity I was playing around with this in node. I was under the impression that if x.__proto__ == X.prototype
then it means x instanceof X
will yield true
until I hit this code with primitive values.
> (2).__proto__ == Number.prototype
true
> 2 instanceof Number
false
> (2) instanceof Number
false
> "abc".__proto__ == String.prototype
true
> "abc" instanceof String
false
> ("abc") instanceof String
false
Why is this?
Upvotes: 2
Views: 93
Reputation: 1074385
instanceof
will always yield false
if the left-hand side is not an object (see Step 3 here).
The reason (2).__proto__ == Number.prototype
is true is that when you apply a property accessor to a primitive (in this case, .__proto__
), a temporary object with the same underlying primitive value is created and used.
So the thing you're getting the __proto__
property from isn't the same thing you're using in your instanceof
cases, because it isn't a primitive. Your test cases would more accurately be:
> (2).__proto__ == Number.prototype true > new Number(2) instanceof Number true
I was under the impression that if
x.__proto__ == X.prototype
then it meansx instanceof X
will yieldtrue
That's true as far as it goes (or would be if you used ===
, for a fairly obscure reason1), but note that the converse is not true: If x instanceof X
is true, that doesn't necessarily mean x.__proto__ == X.prototype
will be true, for a couple of reasons:
It could be that you need to use x.__proto__.__proto__
, or x.__proto__.__proto__.__proto__
, or... :-)
x.__proto__
may well be undefined
. For instance, it is if you create x
like this: x = Object.create(null)
. The reason is that the __proto__
property accessor is provided by Object.prototype
, but if you create an object that doesn't inherit from Object.prototype
, it doesn't have the __proto__
property accessor (on a compliant implementation). This is one reason to use Object.getPrototypeOf(x)
instead.
1 Fairly obscure reason: If x
was created via Object.create(null)
(or using any prototype that doesn't trace back to Object.prototype
) and thus doesn't have the __proto__
property accessor, and X.prototype
is null
, x.__proto__ == X.prototype
would be true
even though they could well be completely and utterly unrelated, since x.__proto__
would be undefined
and undefined == null
is true. ;-)
Upvotes: 6
Reputation: 288170
Primitive values are not objects, and thus are not instances of any constructor.
Your checks will work if you coerce the values to objects:
console.log(Object(2) instanceof Number); // true
console.log(Object("abc") instanceof String); // true
console.log(Object(true) instanceof Boolean); // true
console.log(Object(Symbol()) instanceof Symbol); // true
Upvotes: 2