[Understanding the prototype of personal notes js]

In JavaScript, the most common way to create a new object is to use curly braces. Then use '.' to add properties and methods to it. The following code can be seen:

let animal = {
    
    };
animal.name = 'Leo';
animal.energe = 10;

animal.eat = function (amount) {
    
    
    console.log(`${this.name} is eating.`)
    this.energe += amount
}

animal.sleep = function (length) {
    
    
    console.log(`${this.name} is sleeping.`)
    this.energe += length
}

animal.play = function (length) {
    
    
    console.log(`${this.name} is playing.`)
    this.energe -= length
}

But in common application scenarios, you will need to generate multiple animals. This requires abstracting the above logic into a function. As can be seen from the following code, two animals, leo and snoop, are generated.

function Animal(name, energy){
    
    
    let animal = {
    
    };
    animal.name = name;
    animal.energy = energy;

    animal.eat = function (amount) {
    
    
        console.log(`${this.name} is eating.`)
        this.energy += amount
    }

    animal.sleep = function (length) {
    
    
        console.log(`${this.name} is sleeping.`)
        this.energy += length
    }

    animal.play = function (length) {
    
    
        console.log(`${this.name} is playing.`)
        this.energy -= length
    }
    return animal;
}

const leo = Animal('Leo', 7);
const snoop = Animal('Snoop', 10)

But according to the above code, every time a new animal is created, the eat, sleep, and play methods inside need to be recreated.

Because the eat, sleep, and play methods are very similar, we can put them in an animalMethods, so that they only need to be created once in memory. Then every time we need to create a new animal, we just point to the methods in animalMethods instead of recreating these methods.

const animalMethods = {
    
    
    eat(amount) {
    
    
        console.log(`${this.name} is eating.`)
        this.energy += amount
    },
    sleep(length) {
    
    
        console.log(`${this.name} is sleeping.`)
        this.energy += length
    },
    play(length) {
    
    
        console.log(`${this.name} is playing.`)
        this.energy -= length
    }
}
function Animal(name, energy){
    
    
    let animal = {
    
    };
    animal.name = name;
    animal.energy = energy;
    animal.eat = animalMethods.eat;
    animal.sleep = animalMethods.sleep;
    animal.play = animalMethods.play;
    
    return animal;
}

In the above code, for example, if animal adds a method poop, you need to add animal.poop = animalMethods.poop to the Animal function. If you want Animal to always point to any method in animalMethods, you can use Object.create() to pass in animalMethods, so that when the corresponding attribute or method cannot be found in Animal, it will search in animalMethods and call the corresponding method.

const animalMethods = {
    
    
    eat(amount) {
    
    
        console.log(`${this.name} is eating.`)
        this.energy += amount
    },
    sleep(length) {
    
    
        console.log(`${this.name} is sleeping.`)
        this.energy += length
    },
    play(length) {
    
    
        console.log(`${this.name} is playing.`)
        this.energy -= length
    }
}
function Animal(name, energy) {
    
    
    let animal = Object.create(animalMethods)
    animal.name = name;
    animal.energy = energy;

    return animal;
}
const leo = Animal('Leo', 7);
console.log(leo.play(7)) //Leo is playing.

The above usage is the origin of JavaScript prototype.

So what archetype? It is an attribute on the function that points to an object.

Since prototype is an attribute that every function has, then instead of managing animalMethods separately, why don't we put animalMethods on the prototype of the function?

function Animal(name, energy) {
    
    
    let animal = Object.create(Animal.prototype)
    animal.name = name;
    animal.energy = energy;

    return animal;
}

Animal.prototype.eat = function (amount) {
    
    
    console.log(`${this.name} is eating.`)
    this.energy += amount
}
Animal.prototype.sleep = function (length) {
    
    
    console.log(`${this.name} is sleeping.`)
    this.energy += length
}
Animal.prototype.play = function (length) {
    
    
    console.log(`${this.name} is playing.`)
    this.energy -= length
}

const leo = Animal('Leo', 7);
console.log(leo.eat(5)) //Leo is eating.

The above code tells us three things:

How to create a constructor (a constructor is to construct an object)
How to add methods to the prototype of the constructor (eg: Animal.prototype.eat()={…})
How to use Object.create() to point to the function prototype.
The purpose of these three points is to enable all instances of the constructor to share the methods on the instance.

Next, the keyword new will be introduced to further optimize the above code. Using the new keyword, js will automatically perform the Object.create() and return actions, and you need to use this object to replace the original animal object.

function Animal(name, energy) {
    
    
    // let this = Object.create(Animal.prototype) //这一步的作用:1、创建对象 2、指向Animal.prototype
    this.name = name;
    this.energy = energy;

    // return this; //输出创建的对象
}

Animal.prototype.eat = function (amount) {
    
    
    console.log(`${this.name} is eating.`)
    this.energy += amount
}
Animal.prototype.sleep = function (length) {
    
    
    console.log(`${this.name} is sleeping.`)
    this.energy += length
}
Animal.prototype.play = function (length) {
    
    
    console.log(`${this.name} is playing.`)
    this.energy -= length
}

const leo = new Animal('Leo', 7);
const snoop = new Animal('Snoop', 10)
console.log(leo.sleep(15)) //Leo is sleeping.

The above operations basically create a class. In es6, JavaScript has the class keyword. Next, use class to refactor the above code.

class Animal {
    
    
    constructor(name, energy) {
    
    
        this.name = name
        this.energy = energy
    }
    eat(amount) {
    
    
        console.log(`${this.name} is eating.`)
        this.energy += amount
    }
    sleep(length) {
    
    
        console.log(`${this.name} is sleeping.`)
        this.energy += length
    }
    play(length) {
    
    
        console.log(`${this.name} is playing.`)
        this.energy -= length
    }
}

const leo = new Animal('Leo', 7);
const snoop = new Animal('Snoop', 10)
console.log(leo) //Animal { name: 'Leo', energy: 7 }
console.log(leo.sleep(1)) //Leo is sleeping.

Since you can use js to build classes, why do you need to spend so much time understanding the above prototype, this, new? The reason is that class is syntactic sugar for function, providing a more convenient way to create objects. The class will eventually be compiled into a function, and the methods in it will become shared methods on the prototype.

Guess you like

Origin blog.csdn.net/weiyi47/article/details/132644058