I. Two prototypes
Many people know that javascript is prototype inheritance, and each constructor has a prototype member. Through it, the inheritance of javascript can be magnificent.
Actually, this property alone cannot inherit javascript.
The prototype inheritance we use in the Code is not described here. You can check the information.
Another invisible prototype member.
Each instance has a prototype attribute pointing to the prototype, which cannot be accessed and cannot be modified because it is the basis for maintaining javascript inheritance.
1 // The constructor declares 2 function Guoyansi () {} 3 function GuoyansiEx () {} 4 // The prototype inherits 5 GuoyansiEx. prototype = new Guoyansi (); 6 // create object 7 var g1 = new GuoyansiEx (); 8 var g2 = new GuoyansiEx ();
The objects in the above Code can be described in the following figure.
Ii. Prototype Maintenance
The constructor attribute of an instance generated by a constructor always points to this constructor. We currently think this is correct.
1 function Guoyansi(){ }2 var obj1=new Guoyansi();3 console.log(obj1.constructor===Guoyansi);//true
In fact, the constructor itself does not have the constructor attribute. So where does this attribute come from?
The answer is: from the prototype.
Therefore, the following conclusions are drawn:
1 guo.constructor===Guoyansi.prototype.constructor===Guoyansi
Since we can use constructor to find the constructor, we can further improve the figure above.
1 function GuoyansiEx(){}2 GuoyansiEx.prototype=new Guoyansi();3 console.log(GuoyansiEx.constructor===GuoyansiEx)//false
The above result should be true, but why is it false?
Now let's make an analysis.
The GuoyansiEx prototype is overwritten by the Guoyansi instance. Therefore, the constructor in the GuoyansiEx prototype is also an instance from Guoyansi.
The constructor in the Guoyansi instance comes from Guoyansi. prototype, while Guoyansi. prototype is not overwritten,
Therefore, the constructor of Guoyansi. prototype points to Guoyansi (constructor );
Based on the above analysis, the following conclusions are drawn:
GuoyansiEx.constructor===Guoyansi.constructor===Guoyansi;
If the Constructor point requirements are very accurate during the development process, you can do the following.
/** Method 1 :**/
1 function Guoyansi () {} 2 function GuoyansiEx () {} 3 GuoyansiEx. prototype = new Guoyansi (); 4 GuoyansiEx. prototype. constructor = GuoyansiEx; // reset constructor.
1/** 2 method 2 3 **/4 function Guoyansi () {} 5 function GuoyansiEx () {6 this. constructor = arguments. callee; 7} 8 GuoyansiEx. prototype = new Guoyansi ();
1/** 2 method 3 3 **/4 function Guoyansi () {} 5 function GuoyansiEx () {6 this. constructor = GuoyansiEx; 7} 8 GuoyansiEx. prototype = new Guoyansi ();
3. What is the purpose of an invisible prototype?
We can operate on the visible prototype chain to complete our inheritance, so we can neither see nor operate this invisible prototype chain. What is the purpose of this invisible prototype chain.
The inheritance of Object-oriented has a feature: similarity. child classes are similar to parent classes. therefore, in the subclass, you cannot use delete to delete the members inherited from the parent class. that is to say, the subclass must have the features of the parent class.
To maintain this feature, javascript generates an invisible prototype attribute inside the object and does not allow users to access it. In this way, users can modify the constructor for any purpose,
The sub-classes have the features of the parent class.
In short: the internal prototype is required by the prototype Inheritance Mechanism of javascript, while the external prototype is required by the user to implement the inheritance.
4. _ proto _ in SpiderMonkey of Firefox Engine __
Or this code.
1 function Guoyansi () {} 2 Guoyansi. prototype. age = 24; 3 function GuoyansiEx () {} 4 var obj1 = new Guoyansi (); 5 GuoyansiEx. prototype = obj1; 6 GuoyansiEx. prototype. constructor = GuoyansiEx; // reset the point of the constructor. 7 var obj2 = new GuoyansiEx ();
I want to access the age of the prototype attribute of the parent class Guoyansi from obj.
The idea is as follows.
Step 1: obj2 ===> obj2.constructor. prototype
Part 2: obj2.constructor. prototype ==> GuoyansiEx. prototype;
Part 3: GuoyansiEx. prototype ==> obj1;
Part 4: obj1.constructor ===> Guoyansi
Part 5: Guoyansi. prototype. age
Write as follows: console. log (obj2.constructor. prototype. constructor. prototype. age) // 24;
The final result is 24.
The final result is 24. It can be executed normally, but many books say that after the constructor is modified, the level cannot find the prototype in the parent class. I don't know what is going on.
A more concise property is provided in Firefox. _ proto _
By default, SpiderMonkey adds a property named _ proto _ on any created object, pointing to the prototype used by the constructor.
In fact, it is the invisible prototype chain we mentioned above, but it is only made public in disguise in this place.
You can access the age
Console. log (obj2. _ proto _. _ proto _. age); // 24
In this way, the prototype attribute of the parent class is successfully accessed, but this attribute only applies to Firefox, and errors may occur in other browsers.
In E5, Object. getPrototypeOf () is extended to the Object, and the prototype of all parent classes can be accessed.
1 function Guoyansi () {} 2 Guoyansi. prototype. age = 24; 3 function GuoyansiEx () {} 4 var obj1 = new Guoyansi (); 5 GuoyansiEx. prototype = obj1; 6 GuoyansiEx. prototype. constructor = GuoyansiEx; // reset the point of the constructor. 7 var obj2 = new GuoyansiEx (); 8 var proto = Object. getPrototypeOf (obj2); 9 while (proto) {10 console. log (proto. constructor); 11 proto = Object. getPrototypeOf (proto); 12} 13 console. log ("object prototype" + proto );
Result: GuoyansiEx
Guoyansi
Object
Object prototype null
I personally think this should be one of the essence of javascript object-oriented.