One day, I attended a teacher’s open class and understood the prototype chain with a picture.

It took the teacher two days to understand and tidy up, and he spoke for two hours before we understood.

Today I have sorted him out and shared with you. And let me strengthen and deepen myself.

Here it is:

I’ve numbered each line for better comparison, and I’ll use the numbers in this picture for the rest of the details:

For better comparison reading, you can open the picture by itself and look at the text in comparison.Of course, I will also be close to the corresponding area of the small map posted near the copy.

Front knowledge

Before taking this diagram apart in detail, let’s talk about some of the basics. So we can understand it better later.

  • Function, Object, Array, String, Symbol, etc. These are JavaScript built-in functions, also known as native functions (they exist when JS is created and are provided internally).
  • Prototype: a prototype object.
  • __proto__ : Implicit prototype, private property of an object;
  • All functions are constructed by Function, including Object and other native functions. Each Function is, so to speak, an instance of the Function type.
  • Functions are actually objects, but in a special way, we call them function objects
  • Each function is created with a prototype that represents the prototype of the function. He’s the prototype
  • Each object has a private __proto__ attribute that points to the prototype object of that object’s constructor. Functions as objects also have __proto__
  • Prototype is an Object constructed from Object. So he also has __proto__, which always refers to the Object constructor Object prototype.
  • Functions are constructed by Function, so each Function’s __proto__ refers to Function’s prototype.
  • Object. Prototype’s __proto__ can no longer point to its own infinite loop, so it points to null
  • __proto__ points to its own prototype. Because Function was not constructed, it was born with.

Function a has both prototype and __proto__

The built-in function Object has both prototype and __proto__

Objects have only __proto__

Formula refined

In order to better grasp, I summarized the relevant knowledge points into the following tips. We’ll use that in the next analysis.

  1. Functions are constructed from Function
  2. All functions are objects
  3. As long as it is a function object, there are two attributes: prototype and implicit prototype __proto__.
  4. Normal objects have only __proto__, no prototype
  5. The __proto__ of the instantiated object points to the constructor’s prototype
  6. All function prototypes refer to their own prototype
  7. All prototype __proto__ points to Object. Prototype (except Object)
  8. All Function objects’ __proto__ refers to function. prototype (including Function itself)
  9. Objects have constructor pointing to the function itself

Note: Special cases such as prototype chain pointing to modification and Object.create(NULL) are not considered here

Dissecting a picture

Let’s take a formal look at each detail of the diagram, based on the basics and tips

Legend:

Before looking at a picture, let’s look at its legend

The right side shows the type of node:

Green square: ordinary objects, such as the usual creation of objects obj {}, arr **[]** and other red square: function objects, that is, functions. He is a special kind of object.

The left side indicates the direction of the arrow:

Green arrow: creates instantiated object with new + constructor call White arrow: points to the current node prototype object Blue arrow: points to the current node’s __proto__ private property

details

Function

Let’s start with Function (color block 1) on the far right.

It is an internal Function of JS, and when you print Function you get the result marked “native code”.

Which means he’s been with JS since the beginning.

And he was born with his prototype: function.prototype. Prototype is a function-specific symbol. Each function is created with a prototype property that represents its prototype object. All function prototypes refer to their own prototype. Function. Prototype refers to a Function prototype. So function. prototype === function. prototype (line A in figure)

And then the more special function.__proto__

Function is a Function, and a Function is a special kind of object. So the __proto__ flag, which is unique to objects, also has one on functions. The __proto__ of an instantiated Object refers to the constructor’s prototype, and the __proto__ of all prototypes refers to Object. Prototype (except Object)

// const obj = new Object() // const obj = new Object() // const obj = {} Its implicit prototype __proto__ points to the prototype of the constructor ObjectCopy the code

Therefore, function.__proto__ should also refer to the prototype of Function’s constructor. But because Function is special, it is the ancestor level Function, it is the creation of all things in JS, can not say who constructed it, so Function __proto__ direction is special, it does not have its own constructor, so it points to its own prototype. Function.__proto__ points to its own prototype function.prototype. So function.__proto__ === function. prototype (line B in figure)

This is the first special point in the prototype chain. Prototype: All Function objects’ __proto__ refers to function. prototype (including Function itself)

Extension:

The prototype object has a constructor attribute that refers back to the constructor itself. So the Function. The prototype. The constructor = = = Function

Object

Besides, the Object. (Color block 3) We’ve seen the creation function written in this way:

const obj = new Object()
Copy the code

So Object is a function. But at the same time a function is an object. So Object is a function Object. As long as it is a function object, there are two attributes: prototype and implicit prototype __proto__.

Let’s look at Object.prototype first. Object as a function, it has its own prototype: Object.prototype. Prototype === object. prototype (line D in figure)

__proto__ Object as a Function, it is constructed by Function. It looks like this :(line c in the picture)

const Object = new Function()
Copy the code

So Object is an instantiated function Object. __proto__ === function.prototype; / / All instantiated objects’ __proto__ refers to the constructor’s prototype. (Line F in the picture)

Prototype of prototype

Let’s analyze the prototype of two built-in functions:

Function.prototype.__proto__ Function. Prototype = Function/prototype = Function/prototype The __proto__ of all instantiated objects refers to the constructor’s prototype, and the __proto__ of all prototypes refers to Object. Prototype (except Object) So all prototype objects’ __proto__ points to the Object constructor’s prototype. Implicit archetypes that include Function archetypes and also refer to Object archetypes. __proto__ === object.prototype. (Line G in the picture)

Object.prototype.__proto__ Object. Prototype is a normal Object, and its implicit prototype __proto__ should also refer to the constructor prototype. But since prototype objects are constructed from Object functions, object.prototype. __proto__ should also refer to Object.prototype. But this endless loop doesn’t make sense. So here’s the second special point in the prototype chain: make the Object. Prototype’s prototype point to NULL to end the cycle. Object.prototype.__proto__ === null (Line E in the picture)

Prototype: All prototype __proto__ points to Object. Prototype (except Object)

Fortunately, the Object. Prototye constructor is still honest and knows its ancestor, so its constructor property remains Ojbect. Object.prototype.constructor === Object

Custom function

We all know that when we create an Object, Array, or function as a literal, we create a new Object(), or a new Array(), or a new function. (Line H in the picture)

var obj = {}; Var obj = new Object(); var arr = []; Var arr = new Array(); Function Person() {} function Person() {}Copy the code

So objects, arrays, functions, these are all instantiated objects. Objects and arrays, more on that later, are custom objects. Let’s start with the function we created — the custom function. (Color block 5 in figure)

A “custom function” is a function Object, just like an Object. The names of the custom functions, such as Person, Animal, clickHandle, etc., are user-defined. Object, Array, etc., are native to JS. But remember: as long as it’s a function object, it has prototype and implicit prototype __proto__ attributes.

Prototype (color block 6). Constructor refers back to the function itself.

So person. prototype === person. prototype (line I in figure)

And a custom function prototype. __proto__ custom function prototype as an ordinary Object, constructed from a Object, its prototype __proto__ must point to the Object. The prototype. Function. Prototype According to the formula: All instantiated objects’ __proto__ points to the constructor’s prototype, and all prototype’s __proto__ points to Object. Prototype (except Object) so custom functions. Prototype. __proto__ === Object. The prototype. (Line J in the figure)

Therefore, the __proto__ of the instantiated object (in this case, the custom function) points to the prototype of the constructor. Function. Prototype (including Function itself); Function. Prototype (including Function itself); The constructor of all custom functions is Function, whose prototype is on the right. __proto__ === function.prototype (Line K in the picture)

Custom object

With custom functions out of the way, let’s talk about custom objects. Objects such as obj and arr are the same as those instantiated by “new + constructor ()” (line L).

const object = new Object()
const person = new Person()
Copy the code

Using this Person as an example, consider the green block 7: custom object in the figure below

Since it is called a custom object, it must be just an object. The normal object has only __proto__, and the __proto__ of the normal object (instantiated object) points to the constructor’s prototype. According to the formula: __proto__ points to the prototype constructor of the custom object so person.__proto__ === Person. The prototype. (Line M in the picture)

Thus the (instantiated) custom object in the figure.__proto__ points to the above custom function prototype.

So far, we’ve gone through this picture.

conclusion

  • Function.__proto__ === Function. Prototype
  • Function.prototype === Function.prototype
  • Function.prototype.constructor === Function
  • Function.prototype.__proto__ === Object.prototype
  • Object. __proto__ = = = the Function prototype.
  • Object.prototype.__proto__ === null
  • Person.__proto__ === Function.prototype
  • Person.prototype.__proto__ === Object.prototype
  • person.__proto__ === Person.prototype

Prototype chain

Since prototype object prototype is itself an object, it also has an implicit prototype __proto__. Implicit stereotype pointing rules remain unchanged, pointing to the constructor stereotype; In this case, stereotype -> implicit stereotype, implicit stereotype -> stereotype. Starting from an object and looking for the direction of the implicit prototype in turn, a chain will be formed, which is called the prototype chain. When looking for an object member, if the object itself does not have that member, it looks in the prototype chain.

In the figure above and summary we see that the __proto__ of a custom object points to the prototype of a custom function. The prototype of a custom function is also an Object. Although it has been created since the function was born, it is also built as an Object function Object. So __proto__ on a custom function prototype points to an Object prototype Object. Object. Prototype points to null. Note that the leftmost line actually forms a chain: custom Object -> custom function prototype -> Object prototype -> NULL. When we cannot find an attribute or method on the lowest custom object, JS will look up the prototype chain and return if it finds one, until null returns undefined.

Similarly, Function -> Function -> Object -> NULL forms the prototype chain. When we call a method or property on a function, we look up layers to NULL according to the look-up rules of the prototype chain.

That’s why the call, apply, and bind functions are defined in the Function prototype, and we can also use person. call and person. apply; HasOwnProperty, isPrototypeOf these functions are defined on the Object prototype, we can also use Person. IsPrototypeOf, obj.hasOwnProperty.

Function Person() {console.log(' I am the Person function '); } let obj = new Object() let person = new Person() console.log(person.hasOwnProperty('a')); // Prototype chain lookup: Person -> person.__proto__(prototype) -> person.proto__ (Object. Prototype) Execute a call to console.log(person.call ()); Prototype: Person -> Person.__proto__ (Function. Prototype) call console.log(obj.xxx) Obj -> obj.__proto__ (Object. Prototype) -> null undefinedCopy the code

Knowledge expansion

Function objects and ordinary objects

Normal objects are created/constructed from the new Function() Function objects are constructed from the new Function()

All objects are created using the new function ()

  • This function is called a constructor;
  • The objects created are called instantiated objects
  • When an object is assigned to a variable, the variable holds an address that points to the memory in which the object resides.

A function is also an object that is passednew Function()To create the

Prototype object

The essence of a prototype: An object. Prototype is also called a prototype object. Prototype objects also have a prototype Object of their own: __proto__ All functions have the prototype attribute prototype. By default, prototype is an Object Object. That is, created by the Object constructor, whose prototype refers to the Object prototype. Prototype contains a default property: constructor, which points to the function Object itself. Prototype contains a default property: __proto__, which points to the constructor’s prototype.

Implicit prototype __proto__

All objects have an implicit prototype: the __proto__ attribute An implicit prototype is an object that points to the prototype that created the object. When a prototype looks for an object member, it will look in the implicit prototype if the object does not have that member itself. Object. Prototype. Return undefined if null is not found.

__proto__ is not a feature of the language itself, it is a private attribute added by various manufacturers. Although many modern browsers provide this private attribute in the JS engine, it is still not recommended to use this attribute in production to avoid environment dependence. In production, we can use the Object.getProtoTypeof method to get the prototype of the instance Object and then add methods/properties to the prototype. From ES6

Implicit archetypes and the root causes of archetypes:

Js has no metadata for record types. Therefore, JS can only find the prototype that created its function through the implicit prototype of the object, and thus determine its type.

Two special cases

Function’s implicit stereotype points to its own stereotype. Object’s implicit stereotype points to NULL

Two fixed cases

All implicit prototypes for functions point to prototypes for Function (including Function itself) and all implicit prototypes for functions point to prototypes for Object. (Excluding the Object prototype itself)

constructor

Constructor points to the function itself:

thinking

What’s on the Function prototype?

Execute the following code to create a normal function.

function a(){}
Copy the code

A = Function. Prototype = Function. Prototype = Function.

As you can see from the diagram, a.prototype.__proto__, the prototype of Function:

  • There are function methods: call, apply, bind, toString, constructor, Symbol; (Call, apply, bind)
  • There are properties: Arguments, Caller, and getters and setters for both properties;
  • Finally, there are objects: __proto__ points to its constructor prototype (object.prototype).

What’s on the Object prototype?

Methods: hasOwnProperty, isPrototypeOf, propertyIsEnumerable, toLocaleString, toString, valueOf, and Constructor Get __proto__, set __proto__, presumably to return null for interception. The flags are get __proto__ and set __proto__

Other exploration questions

What are the prototype array functions? What are the prototypes of custom functions?

Practice the interview questions

The last two interview questions are welcome to discuss in the comments section:

Let us go hand in hand with the front road, pay attention to the public number [front mark].