Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between `this instanceof String` and `"foo" instanceof String`?

Tags:

javascript

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?

like image 803
pyk Avatar asked Mar 03 '14 21:03

pyk


People also ask

What is the difference between Instanceof and Typeof?

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.

What is an Instanceof operators in JavaScript?

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 .

How do I know JavaScript Instanceof?

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.

What does Instanceof do in typescript?

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.


3 Answers

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.

like image 65
Felix Kling Avatar answered Nov 05 '22 14:11

Felix Kling


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
like image 42
kevingessner Avatar answered Nov 05 '22 13:11

kevingessner


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.

like image 1
Chuck Avatar answered Nov 05 '22 12:11

Chuck