When we define a function, the function itself will have a prototype attribute by default. However, if we use the new operator to generate an object, there will be no prototype attribute. Let's look at an example to illustrate this
function a( c){
this.b = c;
this.d =function(){
alert(this.b);
}
}
var obj = new a( 'test');
alert(typeof obj.prototype);//undefine
alert(typeof a.prototype);//object
As can be seen from the above example, the function The prototype attribute points to an object. This object is the prototype object. Please see the figure below.
a.prototype contains 2 attributes, one is constructor and the other is __proto__
This constructor is our constructor a, which is also easy to understand.
So what is __proto__?
This involves the concept of prototype chain:
Each object will initialize an attribute inside it, which is __proto__. When we access the attributes of an object, if this attribute does not exist inside the object, then he will look for it in __proto__ Attribute, this __proto__ will have its own __proto__, so I kept looking for it.
Please see mozzlia’s description of it
When an object is created, its __proto__
property is set to constructing function's prototype
property. For example var fred = new Employee();
will cause fred.__proto__ = Employee.prototype;
.
This is used at runtime to look up properties which are not declared in the object directly. E.g. when fred.doSomething()
is executed and fred
does not contain adoSomething
, fred.__proto__
is checked, which points to Employee.prototype
, which contains a doSomething
, i.e. fred.__proto__.doSomething()
is invoked.
Note that <em>__proto__</em>
is a property of the instances, whereas prototype
is a property of their constructor functions.
Whether you believe it or not, let’s take a look at the picture
If you add alert(obj.__proto__ === a.prototype) //true
Similarly, here we analyze what the new operator does
- var obj={}; In other words, initialize an object obj.
- obj.__proto__=a.prototype;
- a.call(obj); that is to say, constructing obj can also be called initializing obj.
Let’s modify this example to make it a little more complicated.
function a(c){
this.b = c;
this.d =function(){
alert(this.b);
}
}
a.prototype.test = function(){
alert( this.b);
}
var obj = function (){}
obj.prototype = new a('test');
obj.prototype.test1 =function(){
alert(22222);
}
var t = new obj('test');
t.test();//alert('test');
Let’s analyze this process
From var t = new obj('test'); we can get t.__proto__ = obj.prototype, but above specifies obj.prototype =new a('test') ; You can look at it this way
obj.prototype = p, p = new a('test'); p.__proto__ = a.prototype;
Then obj.prototype.__proto__ = a .prototype, from t.__proto__ = obj.prototype, it can be concluded that t.__proto__.__proto__ = a.prototype,
So the object t first looks for its own prototype to see if there is a test function. If it is found that there is not, the result will be Go to the upper level, that is, t.__proto__, that is, obj.prototype to find the test function, but obj.prototype does not have this function, and then search higher. That is,
t.__proto__.__proto__ is found. Since t.__proto__.__proto__ = a.prototype, this method is found in a.prototype, and alert('test') is output.
From here It can be analyzed and concluded that the essence of the prototype chain in js lies in __proto__
Look at another example
function a(c){
this.b = c;
this.d =function(){
alert(this.b);
}
}
var obj = new a('test');
alert(obj.constructor);//function a(){}
alert(a.prototype.constructor);//function a() {}
According to the __proto__ mentioned above, let’s analyze it. First of all, obj does not have the attribute constructor, but obj.__proto__ = a.prototype; just start from
a Search in .prototype, and a.prototype.constructor is just a, so the results of both are the same.