在 JavaScript 中,最常见的新建一个对象的方式就是使用花括号的方式。然后使用’ . '的方式往里面添加属性和方法。可见以下代码:
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
}
但通常的应用场景下,你会需要生成多种动物。这则需要把以上的逻辑抽象成一个函数。可见以下代码,生成了 leo 和 snoop 两个动物。
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)
但是按照上面代码,每次新创建一个animal,就需要把里面的eat、sleep、play方法都会被重新创建一遍。
因为eat、sleep、play方法都很相似,所以我们可以把他们放在一个animalMethods里面,这样只需要在内存里面创建一次。然后每次我们需要创建一个新动物,我们只是指向了animalMethods里面的方法,而不是重新创造这些方法。
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;
}
以上代码中,比如animal增加一个方法poop,就需要到Animal函数 里面增加 animal.poop = animalMethods.poop 。 如果想要Animal总能指向 animalMethods里面的任何一个方法,可以使用Object.create()传入animalMethods,使得在Animal里面找不到对应属性或方法时,就会去animalMethods查找,并调用对应方法。
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.
以上的用法就是JavaScript 原型(prototype)的由来。
那么什么原型?它就是函数上的一个属性,指向一个对象。
既然原型是每个函数都有的属性,那么与其单独管理 animalMethods ,为什么我们不把 animalMethods 放到函数的原型上呢?
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.
以上代码告诉了我们三点:
如何创建一个构造函数(构造函数就是构造一个对象)
如何将方法添加到构造函数的原型上(eg:Animal.prototype.eat()={…})
如何使用Object.create()指向函数原型。
这三点的目的就是为了构造函数的所有实例都能共享实例上的方法。
接下来会引入关键词 new 来对上面代码再进行进一步优化。使用new关键词,js会自动做Object.create()和return的动作,并且需要使用this对象来替换原本的animal对象。
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.
以上这些操作,就是基本上创建了一个class。在es6,JavaScript有了class关键词。接下来就用class来重构以上的代码。文章来源:https://www.toymoban.com/news/detail-693365.html
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.
既然可以用js建造class,那么为什么还需要花这么多时间了解上面的prototype,this,new?原因是class是function的语法糖,提供了更便捷的方式创建对象。class最终会被编译为function,其中的方法会成为prototype上面的共享方法。文章来源地址https://www.toymoban.com/news/detail-693365.html
到了这里,关于【个人笔记js的原型理解】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!