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.