原型继承
有些公共的属性和方法可以写到父级身上,子级通过继承也可以使用这些属性和方法 JavaScript 中大多是借助原型对象实现继承的特性
声明两个构造函数,分别是Cat和Bird
function Cat() { }
function Bird() { }
Cat和Bird有很多共同点,比如都有两只眼睛,都有两只耳朵,都会叫,都会吃等等,不光猫和鸟都会这些,其他动物也都会,我们可以把它们共有的特征封装到一个Animal构造函数中,
function Animals() {
this.eyes = 2
this.ears = 2
}
Animals.prototype = {
cry() {
console.log('会叫');
},
run() {
console.log('会跑');
},
eat() {
console.log('会吃');
}
}
function Cat() { }
function Bird() { }
因为实例对象可直接访问原型对象中函数,所以把各种动物的原型对象赋值为Animal的实例对象。
//把各种动物的原型对象赋值为Animal的实例对象
Cat.prototype = new Animals()
Bird.prototype = new Animals()
//给赋值后的原型对象添加constructor属性
Cat.prototype.constructor = Cat
Bird.prototype.constructor = Bird
Cat和Bird的实例对象都能访问Animal中的属性和方法
const cat1 = new Cat()
const bird1 = new Bird()
console.log(cat1.eyes);
console.log(bird1.eyes);
cat1.eat()
bird1.cry()
结果:
原型链如下图
组合继承
猫和鸟都有名字,但值不同,那怎样把name属性封装进Animal中并动态改变name的值? 在JavaScript中可以改变this的指向,call就是其中一种,我们将name封装进Animal中后,在Cat构造函数中,执行Animal函数,此时Animal作为普通函数来使用,再通过call将this指向改为Cat的实例对象,执行Animal为Cat对象创建相应的属性
function Animals(name, food) {
this.eyes = 2
this.name = name
this.food = food
}
function Cat(name, food) {
Animals.call(this, name, food)
}
function Bird(name, food) {
Animals.call(this, name, food)
}
Cat.prototype = new Animals()
Cat.prototype.constructor = Cat
Bird.prototype = new Animals()
Bird.prototype.constructor = Bird
然后创建Cat和Bird的实例对象,进行控制台打印查看结果
const Cat1 = new Cat('老虎', '鹿')
const Cat2 = new Cat('蓝猫', '猫粮')
const Bird1 = new Bird('猫头鹰', '老鼠')
const Bird2 = new Bird('杜鹃', '洋辣子')
console.log(Cat1);
console.log(Cat2);
console.log(Bird1);
console.log(Bird2);
结果: