What's the difference between using instanceof and checking the constructor?

Why do the following two lines return different results?

("test" instanceof String) // returns false
("test".constructor == String) // returns true

Tested in the console of chrome version 28.0.1500.95 m

Does it work slightly differently for native types?

Answers:

Answer

constructor is just a property of the internal [[prototype]] property, that can easily be manipulated:

function A(){}
function B(){}
A.prototype.constructor = B;

var a = new A();

console.log(a.constructor); //B

The instanceof operator however checks the internal prototype chain and is not so easily to be fooled, even if you change the complete prototype property of the constructor function:

function A(){}
function B(){}
A.prototype = B.prototype;

var a = new A();

console.log(a instanceof A); //true
console.log(a instanceof B); //false

So, why is "test" instanceof String === false but ("test".constructor == String) === true?

First of all, "test" is a primitive and primitives are never an instance of anything. What actually happens when you use instanceof is that the internal [[HasInstance]] method of the constructor is called with the possible instance as an argument. So a instanceof A translates roughly to:

`A.[[HasInstance]](a)`

The ECMA Specs have this to say to [[HasInstance]]: http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.5.3

[[HasInstance]] (V)

Assume F is a Function object.

When the [[HasInstance]] internal method of F is called with value V, the following steps are taken:

  1. If V is not an object, return false.
  2. ....

In other words: If the left hand side of instanceof is not an object, the operator will return false.

("test".constructor == String) === true works for a different reason: If you try to access a property of a primitive, the primitive will be temporarily converted into an object. So "test".constructor is roughly equal to:

(new String("test")).constructor

in which case you are actually creating an object, with a constructor function and requesting the constructor property afterward. So it is no surprise, that it will return String.

Answer

The main difference is that instanceof inspects the object's prototype chain whereas checking the constructor only checks to see if it was created from the same constructor.

Example:

function MyObject() {
    this.sayHi = function() { alert('Hi!'); }   
}

var x = new MyObject();
alert(x.constructor === Object);
alert(x instanceof Object);

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.