Preface
I saw a question like this on segmentfault:
var F = function(){};Object.prototype.a = function(){}; Function.prototype.b = function(){};var f = new F();Q: Can f obtain a and b? What is the principle?
At first glance, I was really confused. After careful study, I found that I still didn’t understand the prototype thoroughly, so I summarized it and filled in a hole~
Function and Object
Before solving the problem, let’s talk about the prototype, prototype chain, and the relationship between Function and Object, which is also the focus of this article.
prototype
When creating a function, a prototype object will be automatically created for it, which can be accessed through the function's prototype property.
Create an instance object of the constructor, which will contain a pointer (internal property) inside it, pointing to the prototype object of the constructor. ECMA-262 The 5th edition of this pointer is called [[prototype]]. Although there is no standard way to access [[prototype]] in scripts, Firefox, Safari, and Chrome support a property __proto__ on each object to access the prototype object of their constructor.
Let me say something important again:
The constructor accesses the prototype object through the prototype property.
The instance object accesses the prototype object through the [[prototype]] internal attribute, and the browser implements the _proto_ attribute for the instance object to access the prototype object.
var F = function () {};var f = new F();// Assuming that the prototype object of F is p, then // F.prototype === p;// f.__proto__ === p;Repeat again. . prototype refers to the relationship between the constructor and the prototype object, and __proto__ refers to the relationship between the instance object and the prototype object.
Prototype chain
Class A inherits B, B inherits C... In fact, there is a prototype object with a pointer pointing to B in the prototype object of A, and a prototype object with a pointer pointing to C in the prototype object... Note that it is the connection between the prototype objects. There is no relationship between the three constructors of ABC, so it is called "prototype chain"~
Assuming a is an instance object of A, the prototype chain of a is shown in the purple line in the figure below, and the orange line connects the constructor and its prototype object.
As can be seen from the figure, the end of the prototype chain is Object.prototype.__proto__ that is, null. When looking for a property or method of a, first look for whether a itself has or not. If not, search along the prototype chain until it is found or finally returned to undefined after null.
Function and Object
The relationship between Function and Object is a bit tangled:
Object is a constructor. Since it is a function, it is the instance object of Function; Function is a constructor, but Function.prototype is an object. Since it is an object, it is the instance object of Object.
All objects are instances of Object, and all functions are instances of Function.
Object is an instance of Function, and Function.prototype is an instance of Object.
The relationship between the two is shown in the figure below.
As can be seen, Object as a constructor, it has the prototype attribute pointing to Object.prototype, and as an instance object, it has the Object.__proto__ pointing to Function.prototype. Function is a constructor, it has a prototype attribute pointing to Function.prototype, and Function is a function, and it is also an instance of Function, so it has Function.__proto__ pointing to Function.prototype, so Function.__proto__ === Function.prototype is true.
It can be verified under the Chrome console, as shown in the figure.
Analysis of the original question
The best way to solve the problem of prototype chain is to draw a picture. After the previous analysis, this picture should not be a problem, as follows ~
The prototype chain of f is drawn by a blue line, so f can access a, but b cannot access.
If you don't draw a picture, at first glance, you may think that f can access b. It may be like me that F.prototype points to Function.prototype, but in fact, F.prototype is an object rather than a function, so its prototype object will not be Function.prototype.
Therefore, you should draw a picture whenever the prototype chain problem is ~
Extended topic
In the above question, f can only access a, but not b. But F can access both a and b. If you modify the question to the following, what is the result of Fb()? Why? You can think about it~
var F = function(){};Object.prototype.a = function(){}; Function.prototype.b = function(){ console.log('F.__proto__') }; F.prototype.b = function (){console.log('F.prototype');};Summarize
After reading this, have you found a special feature of the function?
For a general object, there is only one __proto__ attribute used to access the prototype object of its constructor, and for a function, it is both a function and an object.
As a function, it is born with a prototype attribute pointing to its prototype object function name.prototype.
As an instance object of Function, it has the __proto__ attribute pointing to Function.prototype
Usually, these two properties point to two objects, but both of the properties of Function point to the same, both point to Function.prototype.
For function A( ), the methods in A.prototype are for call to its instance object and will not be used by itself; when A is run as an instance, the methods in A.__proto__ are called. In other words, when used as a constructor, the A.prototype chain is taken, and the methods and attributes are assigned to their examples; when used as an object, the A.__proto__ chain is taken. In different scenarios, it is not wrong to distinguish its identity.
After the whole article, I feel that what I said is quite nagging... Please correct me if there are any shortcomings~ As for the question, I really don’t know what to call it. .
May this article bring you some gains after reading it~ ^_^
Thank you for your support for this website. We will continue to update relevant information in the future to help you learn and understand this part of the knowledge!