You don't understand the prototype chain. Take a brick and shoot yourself. Don't shoot me

Many beginners always think it is difficult to contact the prototype chain. In fact, it is not. As long as they understand several attributes, the prototype chain can be understood clearly

Constructor

When we create an object, we need to define a constructor.

Is there anything special about constructors? But no, it's just an ordinary function. It's just that we artificially change the initial letter to uppercase. When we create an object, we add new before executing the constructor to get the object instance. At this time, there is the story of the prototype chain.

function Foo(name) {
     this.name = name;
     this.nationality = "China"
}

let foo = new Foo("Hu Sanfeng");
console.log(foo.name)

Prototype (prototype properties)

After the above constructor is created, we can happily create objects:

function Foo(name) {
     this.name = name;
     this.nationality = "China"
 }

 let foo1 = new Foo("Hu Sanfeng");
 let foo2 = new Foo("Hu xiaocrazy");

If you are as like as two peas, you will have some problems with the code. When we create objects foo1 and foo2, attribute nationality is exactly the same content. Every time we generate an instance, we must occupy more memory for duplicate content, and the same efficiency will also decrease. This is only an attribute. If the attribute and method are more, the memory consumption will be bigger. How to solve this problem?

When defining a function, the function will have a prototype attribute, which is what we call prototype.

We can assign some public properties (such as nationality) and methods to the function prototype. When we create an object, we can directly access the properties and methods in the prototype. This solves the memory consumption problem, because the properties and methods bound to the prototype will not be created repeatedly when we create an object instance.

function Foo(name) {
    this.name = name;
}

Foo.prototype.nationality = "China"
let foo = new Foo("Hu Sanfeng");
console.log(foo.nationality)

In fact, the prototype attribute will exist after we define the constructor. It is essentially an object with some own attributes and methods. Of course, we can also re execute the prototype, just re assign the value, as follows, but I don't think it's necessary in practical application and don't change it. Isn't it fragrant to assign the value directly as an attribute?.

function Foo(name) {
    this.name = name;
}

Foo.prototype = {
    nationality: "China" 
}

let foo = new Foo("Hu Sanfeng");
console.log(foo.nationality)

__proto__

Why can the above objects directly access the properties and methods in the prototype?

Because there are in the instance object__ proto__ ( It is the prototype chain we often talk about. Personally, I think it should not be called prototype chain, but the connection point of prototype chain. It points to the prototype prototype.

function Foo(name) {
    this.name = name;
}

Foo.prototype.nationality = "China"
let foo = new Foo("Hu Sanfeng");
console.log(Foo.prototype == foo.__proto__)   // true 

Top level of prototype chain

You must have heard that the top prototype is null.

Then let's illustrate with an example:

function Foo(name) {
    this.name = name;
}

let foo = new Foo("Hu Sanfeng");
console.log(Foo.prototype == foo.__proto__)

// Foo.prototype is an object, so there must be__ proto__
console.log(Foo.prototype.__proto__ == Object.prototype)  // true

console.log(Object.prototype.__proto__)   // null

The prototype of Foo prototype is Object.prototype, and the prototype of Object.prototype is null.

Prototype chain

Although we already know the prototype related knowledge, what is the prototype chain? How to answer this question:

Prototype chain: Based on the object__ proto__ It is a joint debugging from node to null.

The above sentence may not be easy to understand. Let's take an example:

function Foo() {
    this.a = 1;
}

Foo.prototype.b = 2

Object.prototype.c  = 3

let foo = new Foo();

console.log(foo.a, foo.b, foo.c);  // 1 2 3 

Let's write down the prototype chain of object foo:

//    foo: {
//        a: 1,
//        __proto__: Foo.prototype = {
//            b: 2,
//            __proto__: Object.prototype = {
//                c: 3,
//                __proto__: null
//            }
//        }
//    }

When we access properties separately:
When accessing foo.a, find it directly in the foo object; When foo.b is accessed, the object foo is accessed__ proto__,__proto__ Point to foo.prototype. There is a b attribute in the foo.prototype object; When accessing foo.c, the principle is the same.

Thus, when an object accesses a property or calls a method, it will look up along the prototype chain until it finds the location; If it cannot be found, it returns undefined.

reference material

Tags: Javascript

Posted on Sun, 05 Sep 2021 03:15:10 -0400 by anikin