Topics introduced

First we declare a normal object

let obj = {name:"obj"}
Copy the code

On the console, we type obj.valueof (), obj.toString(), onj.constructor

Before we do anything else to obj, we find that obj already has several properties (methods)

Let’s print the object obj again

Is it strange to think that valueOf/toString/constructor and other methods or properties come from? We didn’t declare these things to OBj. Want to know why, please listen to the following slowly introduce.

Introduction to Constructors

A constructor is simply a function that uses the new keyword to create an instance of it. The first letter of the constructor is usually uppercase.

Instance member: the member added by this inside the constructor. Instance members are accessible only through the instantiated object.

Static member: A member added to the constructor itself that can only be accessed through the constructor

function Person() {
 // Instance members
 this.name = "jimmy";
 this.age = 18;
}
// Static members
Person.sex = 'male';
let person = new Person(); // {name:'jimmy',age:18} 
console.log(person.name) // jimmy
console.log(person.sex); // Undefined instance cannot access sex
console.log(Person.name); The Person constructor cannot directly access instance members
console.log(Person.sex); // The male constructor has direct access to static members
Copy the code

In this case, Person is a constructor, and we use the new keyword to get the instance object Person.

prototype

Each function has a Prototype property.

function Person() {}// Note that prototype is a function property
Person.prototype.name = 'Kevin';
var person1 = new Person();
var person2 = new Person();
console.log(person1.name) // Kevin
console.log(person2.name) // Kevin
Copy the code



Prototype definition:

Every JavaScript object (except null) is associated with another object when it is created. This object is called a stereotype, and every object “inherits” properties from that stereotype.

In this example, name is the prototype object (person.prototype) that inherits from Person.

Var obj = {} is equivalent to var obj = new Object()

__ proto __

Every JavaScript object (except null) has a property called __proto__ that points to the object’s prototype

function Person() {}var person = new Person();
console.log(person.__proto__ === Person.prototype); // true
Copy the code

constructor

Each stereotype object has a constructor property that points to the associated constructor.

function Person() {}console.log(Person === Person.prototype.constructor); // true
Copy the code

That’s the relationship between constructors, prototypes, and instance objects.

To sum up, we can conclude that:

function Person() {}var person = new Person();

console.log(person.__proto__ === Person.prototype) // true
console.log(Person.prototype.constructor === Person) // true

// By the way, learn an ES5 method to get a prototype of an object
console.log(Object.getPrototypeOf(person) === Person.prototype) // true
Copy the code

Instance objects and prototypes

When you read the properties of an instance object, if you can’t find them, you look for the properties in the stereotype associated with the object. If you can’t find them, you look for the stereotype of the stereotype, all the way to the top.

function Person() {

}

Person.prototype.name = 'jimmy';
let person = new Person();
person.name = 'chimmy';
console.log(person.name) // chimmy
delete person.name;
console.log(person.name) // jimmy
Copy the code

In this example, we added the name attribute to the instance object Person, and when we print person.name, the result is chimmy. But when we remove the name attribute of person, and then we read person.name, we can’t find the name attribute from the person object, and then we get the name attribute from the person prototype, which is person.__ proto __, Again in person. prototype, fortunately we found the name attribute, which results in Jimmy.

But what if they haven’t found it yet? What are the archetypes of archetypes?

Prototype of prototype

In fact, the prototype is generated by the Object constructor all the way to the end. As mentioned earlier, the instance’s __ proto__ refers to the constructor’s prototype, so we update the diagram

Prototype chain

What about Object. Prototype? If it’s null, we can print

console.log(Object.prototype.__proto__ === null) // true
Copy the code

If you look up object. prototype, you can stop looking. Null has no prototype.

The chain of interrelated prototypes in the diagram below is the prototype chain, which is the blue line.

The prototype of the constructor

Looking at the diagram above, what is the prototype for the Person constructor?

As mentioned above, every JavaScript object (except null) has a property called __proto__, which refers to the object’s prototype. Since the Person constructor is generated by the Function Function, we conclude the following:

// The Person constructor
function Person(){
}
Person.__proto__ === Function.prototype
Copy the code

The prototype of function. prototype is object.prototype

Function.prototype.__proto__ === Object.prototype  
Object.prototype.__prototo__ === nullAnd that's where the prototype chain ends.nullThere is no prototypeCopy the code

All functions can be created using new Function(), so all functions (including their own constructors) are instances of Function.

The classic picture can finally be shown

If you understand this diagram, you have a basic understanding of prototypes and prototype chains.

supplement

constructor

function Person() {}var person = new Person();
console.log(person.constructor === Person); // true
Copy the code

When you get person.constructor, which actually doesn’t have a constructor property in person, when you can’t get the constructor property, you get it from person’s prototype, which is person. prototype, Just the prototype has the attribute, so: person. The constructor = = = person. The prototype. The constructor

Is it really inheritance?

Every object inherits properties from its prototype. In fact, inheritance is a very confusing term, as in JavaScript you Don’t know: Inheritance means copying operations. However, JavaScript does not copy the properties of an object by default. Instead, JavaScript simply creates an association between two objects, so that one object can access the properties and functions of the other object through a delegate.

What is the meaning of prototype, prototype chain

So let’s look at this and think, what’s the point of archetypes, archetype chains?

The purpose of the prototype object is to store the properties and methods that are common to the instance, which can greatly reduce memory consumption. Take the example of the Person constructor and the Person instance object at the beginning of our article:

function Person(name,age){
 this.name = name;
 this.age = age;
 this.say:() = >{
   console.log("I can talk")}}let person1 = new Person("Xiao Ming".20);
let person2 = new Person("Little red".18)
console.log(person.say===person2.say) // false
Copy the code

Obviously, person1 and Person2 do not point to the same place. So we create an instance by adding this method to the constructor. Each time we create an instance, we create a new memory space for the method. This leads to a huge waste of memory, which affects performance

So let’s add the method through the prototype

function Person(name,age){
 this.name = name;
 this.age = age;
}
Person.prototype.say = () = > {console.log("I can talk")}

let person1 = new Person("Xiao Ming".20);
let person2 = new Person("Little red".18)
console.log(person.say===person2.say) // true
Copy the code

The prototype object holds the method say shared by Person1 and Person2. Instead of generating this method on every instance we generate, we store this property on their constructor prototype objects, for human constructors like Person. There are many, many similar properties and methods, such as we are black hair, we all eat, sleep such a method, when the more similar properties and methods, the more meaning of the prototype, prototype chain. Common properties and methods stored on prototype objects can greatly reduce memory consumption.

Test yourself

1. What to print next

Object.prototype.__proto__  
Function.prototype.__proto__  
Object.__proto__              
Copy the code

2. What to print next

function A(){};
A.prototype.n = 1;
var b = new A();
A.prototype = {
  n: 2.m: 3
}
var c = new A();

console.log(b.n);
console.log(b.m);
console.log(c.n);
console.log(c.m);
Copy the code

3. What to print next

function F() {};
Object.prototype.a = function () {
  console.log("a");
};
Function.prototype.b = function () {
  console.log("b");
};
var f = new F();

F.a();
F.b();
f.a();
f.b();
Copy the code

4. Implement the Person and Student objects as follows

  1. Student inheritance Person
  2. Person contains an instance variable name that contains a method printName
  3. Student contains an instance variable score, which contains an instance method printScore
  4. All Person and Student objects share a method between them

The answer is below

The answer

Object.prototype.__proto__    //null
Function.prototype.__proto__  //Object.prototype
Object.__proto__              //Function.prototype
Copy the code
console.log(b.n);  / / 1
console.log(b.m);  // undefined
console.log(c.n);  / / 2
console.log(c.m);  / / 3
Copy the code
F.a(); // a
F.b(); // b
f.a(); //a
f.b(); // f is not a function
Copy the code

F = f; f = f; f = f; f = f; f = f; f = f; f = f; So we can’t get method B.

__proto__ refers to function.prototype, so the F Function can take the b method

    function Person (name){
        this.name = name;
        this.printName=function() {
            console.log('This is printName');
        };
    }
    Person.prototype.commonMethods=function(){
        console.log('I am the sharing method');
    };

    function Student(name, score) {
        Person.call(this,name);
        this.score = score;
        this.printScore=function() {
            console.log('This is printScore');
        }
    }
    Student.prototype = new Person();
    let person = new Person('the little purple'.80);
    let stu = new Student('little red'.100);
    console.log(stu.printName===person.printName);//false
    console.log(stu.commonMethods===person.commonMethods);//true

Copy the code