Instanceof in parsing JavaScript may return true for different constructors

  • 2020-03-30 00:41:29
  • OfStack

We know that the instanceof operator is used to check whether an object is an instanceof a constructor. Here are the various scenarios where it returns true.

Object obj is created with a new Constructor, so obj instanceof Constructor is true


function Person(n, a) { 
    this.name = n; 
    this.age = a; 
} 
var p = new Person('John Backus', 82); 
console.log(p instanceof Person); // true 

2. If there is an inheritance relationship, the subclass instance instanceof parent class also returns true

function A(){} 
function B(){} 
B.prototype = new A(); //B inherits from A

var b = new B(); 
console.log(b instanceof A); // true 

3. Since Object is the root class and all other custom classes inherit from it, instanceof Object, an instanceof any constructor, returns true

function A() {} 
var a = new A(); 
console.log(a instanceof Object); // true 

var str = new String('hello'); 
console.log(str instanceof Object); // true 

var num = new Number(1); 
console.log(num instanceof Object); // true 

Even the constructor itself

function A() {} 
console.log(A instanceof Object); // true 
console.log(String instanceof Object); // true 
console.log(Number instanceof Object); // true 

4. All constructors instanceof Function return true

function A() {} 
console.log(A instanceof Function); // true 
console.log(String instanceof Function); // true 
console.log(Number instanceof Function); // true 

The four points above are summarized in one sentence: Instanceof returns true if an instance is created by a class or subclass. Or if the prototype of a constructor exists in the inner prototype chain of the object obj, it returns true. That is, the results of instanceof are not directly related to the constructor itself. This is common in many languages.

A class Person is defined in Java, and the instance p returns true for both Person and Object


class Person { 
    public String name; 
    public int age; 
    Person (String n, int a) { 
        this.name = name; 
        this.age = a; 
    } 
    public static void main(String[] args) { 
        Person p = new Person("John Backus", 82); 
        System.out.println(p instanceof Person); // true 
        System.out.println(p instanceof Object); // true 
    } 
} 

If there is an inheritance relationship in Java, the subclass instance instanceof parent class also returns true

//  The parent class  
class Person { 
    public String name; 
    public int age; 
    Person (String n, int a) { 
        name = name; 
        age = a; 
    } 
} 
//  A subclass  
public class Man extends Person{ 
    public String university; 
    Man(String n, int a, String s) { 
        super(n, a); 
        university = s; 
    } 
    public static void main(String[] args) { 
        Man mm = new Man("John Resig", 29, "PKU"); 
        System.out.println(mm instanceof Man); // true 
        System.out.println(mm instanceof Person); //Is also true
    } 
} 

Knowing this, the following behavior in JS is not surprising

//Define two constructors
function A(){} 
function B(){} 
A.prototype = B.prototype = {a: 1}; 

//Create instances of two different constructors
var a = new A(); 
var b = new B(); 
console.log(a instanceof B); // true 
console.log(b instanceof A); // true 

We see that a and b are created with a and b respectively, but both a instanceof b and b instanceof a are true. That is, a returns true even though it was not created with constructor B. Because b.prototype exists on the internal prototype chain of a.

Because of the dynamic language nature of JS, you can modify the prototype at run time, so it's no surprise that the following returns false. Because a.prototype is no longer in the internal prototype chain of a, the chain is broken.


function A(){} 
var a = new A(); 
A.prototype = {}; //Modify the prototype dynamically, noting that it must be after creating a
console.log(a instanceof A); // false 

Note that this also breaks the first rule summarized above: object obj is created with a new Constructor, and obj instanceof Constructor is true

In fact, in the ECMAScript standard (as of 5.1), the instanceof internal implementation calls the internal methods of the constructor [[HasInstance]], as described below

If F is a function object, the following steps occur when F(V) is executed:

1. If the instanceof left operand V is not an object type, return false directly


var a, b = 1, c = true, d = 'hello'; 
console.log(a instanceof Object); //False where a is undefined
console.log(b instanceof Object); // false 
console.log(c instanceof Object); // false 
console.log(d instanceof Object); // false 

2/3. Take the prototype property of constructor F. If it is not an object type, a TypeError exception must be thrown.

function A(){} 
A.prototype = 1; //Prototype of A is set to A non-object type
var a = new A(); 
console.log(a instanceof A); 

Each browser throws a different exception,

Firefox18:

< img Alt = "" border = 0 SRC =" / / files.jb51.net/file_images/article/201312/201312030936009.png ">

Chrome24:

< img Alt = "" border = 0 SRC =" / / files.jb51.net/file_images/article/201312/2013120309360010.png ">

Safari6:

< img Alt = "" border = 0 SRC =" / / files.jb51.net/file_images/article/201312/2013120309360011.png ">

Opera12:

< img Alt = "" border = 0 SRC =" / / files.jb51.net/file_images/article/201312/2013120309360012.png ">

Consumer:

< img Alt = "" border = 0 SRC =" / / files.jb51.net/file_images/article/201312/2013120309360013.png ">

4. Continuously execute the following logic: set V as internal prototype V, return false if V is null, and true if V and O both point to the same object.


Related articles: