I'm extending Object like this:
Object.prototype.is_a = function (x) {
return this instanceof x;
}
All works as expected
"foo".is_a(String) // true
"foo".is_a(Object) // true
"foo".is_a(Array) // false
"foo".is_a(Function) // false
"foo".is_a(Boolean) // false
"foo".is_a(Date) // false
"foo".is_a(Number) // false
"foo".is_a(RegExp) // false
but, when
"foo" instanceof String // false
this
keyword on the is_a()
function is same as foo
right? Why does it return different results?
typeof: Per the MDN docmentation, typeof is a unary operator that returns a string indicating the type of the unevaluated operand. instanceof: is a binary operator, accepting an object and a constructor. It returns a boolean indicating whether or not the object has the given constructor in its prototype chain.
The instanceof operator tests to see if the prototype property of a constructor appears anywhere in the prototype chain of an object. The return value is a boolean value. Its behavior can be customized with Symbol. hasInstance .
The JavaScript instanceof operator is used to check the type of an object at the run time. It returns a boolean value(true or false). If the returned value is true, then it indicates that the object is an instance of a particular class and if the returned value is false then it is not.
The Typescript instanceof is one of the operators, and it is used to determine the specific constructor, and it will be creating the object of the classes. It will call the methods with the help of instance like that if we use an interface that can be implemented and extended through the classes.
First of all, you cannot apply instanceof
to primitive values, that's why
"foo" instanceof String
returns false
. Primitives are not objects and hence cannot be an instance of a constructor function. *
So why does it seem to work inside the is_a
method?
In non-strict mode, the value of this
inside a function is always going to be an object (step 3). If this
value is not an object, it is implicitly converted to one. You can test this with console.log(typeof this)
.
That means that the string primitive "foo"
is converted to an String object new String("foo")
and that's why you can use instanceof
on it.
In strict mode, the value of this
doesn't have to be an object and is not automatically converted (step 1). Your method would fail in that case:
> Object.prototype.is_a = function (x) {
'use strict';
return this instanceof x;
}
> "foo".is_a(String)
false
*: That's a very simplified explanation. In reality, the instanceof
operator delegates the evaluation to the constructor function's internal [[HasInstance]]
method, which is defined to return false
if the passed value is not an object.
String literals aren't the same as String objects (MDN). It appears that the string literal (which is a string primitive) is automatically boxed into an object when it's used as the binding context of a function (i.e. when it's this
inside a function):
>>> typeof "foo"
"string"
>>> Object.prototype.type_of = function (x) {
return typeof this;
}
function (x) {
return typeof this;
}
>>> "foo".type_of()
"object"
That explains your instanceof behavior, as well. This behaves as you might expect:
>>> new String("foo") instanceof String
true
>>> new String("foo") instanceof Object
true
>>> new String("foo").is_a(String)
true
>>> new String("foo").is_a(Object)
true
>>> new String("foo").is_a(Array)
false
JavaScript has both primitive and object versions of strings, numbers and booleans. String literals define primitives rather than objects. If you did typeof "foo"
, you would get "string" rather than "object". But when you access a property of the string, it creates a temporary String object from the primitive string and then accesses the corresponding property of that object, so it this instanceof String
is true inside that temporary String object's method.
In order to test whether something is a string while accounting for both primitives and objects, you need to test typeof foo === "string" || foo instanceof String
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With