父类
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、原型继承
function Cat(){ }
//原型链继承
Cat.prototype=new Animal()
Cat.prototype.name="cat"
let cat =new Cat()
console.log(cat.name) //cat
console.log(cat instanceof Animal) //true
console.log(cat instanceof Cat) //true
cat.eat('鱼') //cat正在吃鱼
cat.sleep() //cat父类的方法正在睡觉
优点:写法方便简洁,容易理解。
缺点:对象实例共享所有继承的属性和方法。传教子类型实例的时候,不能传递参数,因为这个对象是一次性创建的(没办法定制化)。
2、借用构造函数继承
function Dog(name){
Animal.call(this,name)
this.name=name||"小狗"
}
let dog=new Dog('贵宾犬')
console.log(dog.name) //贵宾犬
console.log(dog instanceof Animal) //false
console.log(dog instanceof Dog) //true
在子类型构造函数的内部调用父类型构造函数;使用 apply() 或 call() 方法将父对象的构造函数绑定在子对象上。
优点:解决了原型链实现继承的不能传参的问题和父类的原型共享的问题。
缺点:借用构造函数的缺点是方法都在构造函数中定义,因此无法实现函数复用。在父类型的原型中定义的方法,对子类型而言也是不可见的,结果所有类型都只能使用构造函数模式。
3、组合式继承
function Monkey(){
Animal.call(this,name)
this.name=name||"小猴子"
}
Monkey.prototype=new Animal()
Monkey.prototype.constructor=Monkey
let monkey=new Monkey()
console.log(monkey.name) //小猴子
console.log(monkey instanceof Animal); //true
console.log(monkey instanceof Monkey) //true
优点: 解决了原型链继承和借用构造函数继承造成的影响。
缺点: 无论在什么情况下,都会调用两次超类型构造函数:一次是在创建子类型原型的时候,另一次是在子类型构造函数内部