1. 继承的目的
为了更大程度实现代码复用,重复利用另一个对的属性或方法
2. 原型继承
function Animal() {}
Animal.prototype.eat = function () {
console.log(this.name, '正在愉快的吃....', this.voice);
};
function Dog() {
this.name = '小狗';
this.voice = '汪汪.....'
}
// 利用原型对象实现继承
Dog.prototype = Animal.prototype
new Dog().eat() // 小狗 正在愉快的吃.... 汪汪.....
function Cat() {
this.name = '小猫';
this.voice = '喵喵.....'
}
// 利用原型对象实现继承
Cat.prototype = Animal.prototype
new Cat().eat() // 小猫 正在愉快的吃.... 喵喵.....
// 如果修改Cat的原型,会影响后面的结果
Cat.prototype.eat = function () {
console.log('小猫吃不下了')
}
function Sheep() {
this.name = '小羊';
this.voice = '咩咩.....'
}
// 利用原型对象实现继承
Sheep.prototype = Animal.prototype
new Sheep().eat() // 小猫吃不下了
总结:
原型继承方式,是利用对象的共享
1、 优点:方便就在于实现共享
2、 缺点:一方改变会影响一方
3、构造函数继承
function Animal() {
this.eat = function () {
console.log(this.name, '正在愉快的吃....')
}
}
function Dog(name) {
this.name = name
console.log(this) // Dog(){name: '小狗'}
Animal.call(this) // 改变this指向
}
new Dog('小狗').eat(); // 小狗正在愉快的吃....
function Cat(name) {
this.name = name
console.log(this) // Dog(){name: '小猫'}
Animal.call(this)
}
new Cat('小猫').eat(); // 小猫正在愉快的吃....
总结:
构造函数继承方式: 子类调用父类的方法
1、 临时改变this的指向
2、 优点:避免了原型继承的修改影响共享数据
3、缺点,构造函数内的function等属性需要被声明多次
4、组合继承
function Animal() {
this.desc = '他们都是动物'
}
Animal.prototype.eat = function () {
console.log(this.desc)
console.log(this.name, '正在愉快的吃....');
};
function Dog(name) {
this.name = name
Animal.call(this)
}
Dog.prototype = Animal.prototype
// 将Animal的构造器也覆盖了Dog的构造器
Dog.prototype.constructor = Dog; // 恢复回来
var d1 = new Dog('大二哈')
d1.eat() // 大二哈正在愉快的吃.....
// 如果修改Dog的原型,还是会影响其他方的调用
// Dog.prototype.eat= function() {
// console.log('大二哈不吃了')
// }
// 动态的创建一只小狗
var d2 = new d1.constructor('小二哈');
d2.eat() // 小二哈正在愉快的吃.....
组合继承是解决了构造函数继承问题, 但还是具有原型继承的缺点
5、派生继承
派生继承 :基于已有的xx类生成一个新的类,
从另一角度来说,从已有的类(父类)产生一个新的子类
function Animal() {}
Animal.prototype.eat = function () {
console.log(this.name, '正在愉快的吃....');
};
function Dog(name) {
this.name = name
}
var newAnimalProto = Object.create(Animal.prototype); //根据原型创建一个对象
Dog.prototype = newAnimalProto
// 将Dog的构造器恢复过来
Dog.prototype.constructor = Dog
new Dog('二哈').eat();
// 测试修改Dog不会影响Animal
Dog.prototype.dogTpe = '是二哈呀';
console.log(Dog.prototype.dogTpe, Animal.prototype.dogTpe) // 是二哈呀,undefined
派生继承:
避免了原型数据共享修改的弊端
同时如果再结合上构造函数继承等