For example:
Copy codeThe Code is as follows:
// Code 1
Function Pig (){}
Var pig = new Pig ();
Alert (pig instanceof Pig); // => true
Function FlyPig (){}
FlyPig. prototype = new Pig ();
Var flyPig = new FlyPig ();
Alert (flyPig instanceof Pig); // => true
Let's look at another piece of code:
Copy codeThe Code is as follows:
// Code 2
Function Pig () {Pig. prototype = {/* some code */}}
Var pig = new Pig ();
Alert (pig instanceof Pig); // => false
Why is the pig no longer a Pig?
When an object is an instance of a class, it means that this object has the methods and attributes of this class. In JavaScript, the characteristics of a pig are embodied in the prototype:
Copy codeThe Code is as follows:
// Code 3
Function Pig (){}
Pig. prototype = {
"Eat pig": function (){},
"Sleeping": function (){},
"Long queue": function (){}
};
Var pig = new Pig ();
Alert (pig instanceof Pig); // => true
If the feature of pig is changed dynamically, the pig becomes a cow:
Copy codeThe Code is as follows:
// Code 4
Pig. prototype = {
"Grazing": function (){},
"Plow field": function (){}
};
Var niu = new Pig ();
Alert (pig instanceof Pig); // => false
Alert (niu instanceof Pig); // => true
Pig is a pig instance in code 3 because Pig is a Pig instance when prototype of pig is not changed. After prototype is changed, the pig is not a pig, but a pig. Therefore, pig in code 4 is no longer a Pig instance, And niu is a Pig instance.
Before further analysis, let's review the internal mechanism of new. In code 2, new Pig () is equivalent:
Copy codeThe Code is as follows:
// Var pig = new Pig () equivalent pseudocode:
Var pig = (function (){
Var o = {};
O. _ proto _ = Pig. prototype; // line 2
Pig. call (o );
Pig. prototype = {/* some code */}; // line 4
Return o; // line 5
})();
It can be seen that in line 2, o. _ proto _ points to the value pointed to by Pig. prototype. However, In line 4, Pig. prototype points to a new value. That is to say, when line 5 returns, pig. _ proto __! = Pig. prototype. This change makes pig in Code 2 not Pig.
It can be inferred that the reason for judging whether pig is Pig by instanceof is: Check whether the hidden pig. _ proto _ attribute is equal to Pig. prototype!
To further confirm, we can simulate the internal implementation code of instanceof in Firefox:
Copy codeThe Code is as follows:
/**
* Simulate instanceof In the Gecko Engine
*/
Function _ instanceof (obj, cls ){
// The left operand of instanceof must be a non-null object or function object.
If (typeof obj! = "Object" | obj = null)
& Typeof obj! = "Function "){
Return false;
}
// The right operand of instanceof must be a function object
If (typeof cls! = "Function "){
Throw new Error ("invalid instanceof operand (" + cls + ")");
}
// Backtracing
Var p = obj. _ proto __, cp = cls. prototype;
While (p ){
If (p = cp) return true;
P = p. _ proto __;
}
Return false;
}
Test page: simulate-intanceof.html
Finally, you can take the exam:
Copy codeThe Code is as follows:
Function Bird (){}
Var bird = new Bird ();
Var o = {};
Bird. _ proto _ = o;
Bird. prototype = o;
Alert (bird instanceof Bird); // true or false?