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

后端 未结 2 934
傲寒
傲寒 2020-12-03 22:48

Why do the following two lines return different results?

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


        
相关标签:
2条回答
  • 2020-12-03 23:28

    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);
    
    0 讨论(0)
  • 2020-12-03 23:34

    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.

    0 讨论(0)
提交回复
热议问题