首先有个共同的父亲
function Animal(name) {
this.name=name || 'Animal';
this.sleep=function () {
console.log(this.name+'正在睡觉');
}
}
Animal.prototype.eat=function (food) {
console.log(this.name+'正在吃'+food)
}
1、原型链继承 真真
1)优点
- 简单明了,容易实现
- 实例是子类的实例,实际上也是父类的一个实例
- 父类新增原型方法/原型属性,子类都能访问到
2)缺点
- 所有子类的实例的原型都共享同一个超类实例的属性和方法
- 无法实现多继承
function Cat() {
}
Cat.prototype=new Animal();
var cat=new Cat();
console.log(cat.name)
cat.sleep();
cat.eat('fish');
console.log(cat instanceof Animal);
console.log(cat instanceof Cat);
2、构造继承 无法继承父亲的原型属性,可继承多个 假真
实现原理:让父类的构造函数成为子类的方法,然后调用该子类的方法,通过this关键字给所有的属性和方法赋值
1)优点
- 简单明了,直接继承超类构造函数的属性和方法
2)缺点
- 无法继承原型链上的属性和方法
function Cat() {
Animal.call(this);
}
var cat=new Cat();
console.log(cat.name);
cat.sleep();
cat.eat('fish');//报错
console.log(cat instanceof Animal);
console.log(cat instanceof Cat);
3、实例继承 真假
function Cat() {
var animal=new Animal();
return animal;
}
var cat=new Cat();
console.log(cat.name);
cat.sleep();
cat.eat('fish');
console.log(cat instanceof Animal);
console.log(cat instanceof Cat);
4、拷贝继承 假真
function Cat() {
var animal=new Animal();
for(let p in animal){
Cat.prototype[p]=animal[p]
}
}
var cat=new Cat();
console.log(cat.name);
cat.sleep();
cat.eat('fish');
console.log(cat instanceof Animal);
console.log(cat instanceof Cat);
5、组合继承 真真
function Cat() {
Animal.call(this)
}
Cat.prototype=new Animal(); //此时 Cat.prototype 中的 constructor 被重写了,会导致 cat.constructor === Animal
Cat.prototype.constructor = Cat //将 Cat 原型对象的 constructor 指针重新指向 Cat 本身
var cat=new Cat();
console.log(cat.name);
cat.sleep();
cat.eat('fish');
console.log(cat instanceof Animal);
console.log(cat instanceof Cat);
6、寄生组合继承 但是实现条件比较复杂 真真
function Cat() {
Animal.call(this)
}
(function () {
var s=Animal;
s.prototype=Animal.prototype;
Cat.prototype=new s();
})();
var cat=new Cat();
console.log(cat.name);
cat.sleep();
cat.eat('fish');
console.log(cat instanceof Animal);
console.log(cat instanceof Cat);