1.原型链继承
将父类的实例作为子类的原型(利用原型让一个引用类型继承另一个引用类型)
特点:
- 实例是子类的实例也是父类的实例,父类新增的原型方法/属性,子类都能访问
缺点:
- 来自原型对象的所有属性被所有实例共享,
- 无法实现多继承
- 无法给父类构造函数传参
function person(){}
people.prototype = new person()
people.prototype.name = 'lisa'
let obj = new people()
2.借用构造函数继承
复制符类的实例属性给子类(在子类构造函数中调用超类型构造函数)
特点:
- 可以向父类传递参数
- 可以实现多继承(apple或call多个父类)
- 解决了原型中包含实例引用类型被所有实例共享的问题
缺点:
- 方法都在构造函数中定义,无法复用
- 不能继承原型属性和方法
function person(age){
people.call(this)
this.age = age || '20'
}
let obj = new person()
3.实例继承
借助原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型,为父类实例添加新属性,作为子类实例返回
特点:
- 不限制调用方法,new people() / people()
缺点:
- 实例是父类的实例,不是子类的实例
- 不支持多继承
- 包含应用类型的值会被所有实例共享
function person(name){
let people = new person()
people.name = name || 'lisa'
return people()
}
4.拷贝继承
特点:
-
支持多继承
缺点: -
效率较低,内存占用高(因为要拷贝父类的属性)
-
无法获取父类不可枚举(不能使用for in 访问到)的方法
function Cat(name){
var animal = new Animal()
for(for p in animal){
Cat.prototype[p] = animal[p]
}
Cat.prototype.name = name || 'lisa'
}
var cat = new Cat()
console.log(cat.name)
console.log(cat instanceof Animal) //false
console.log(cat instanceof Cat) //true
5.组合继承
调用父类构造函数,继承父类的属性,通过将父类实例作为子类原型
特点:
- 实现函数复用
- 可以继承原型的属性和方法
缺点:
- 调用了两次父类,产生了两个实例
//父类
function People(name,age){
this.name = name || 'lisa'
this.age = age || '20'
}
//方法
Paople.prototype.eat = funciton() {
return this.name + this.age +'eat food'
}
//子类
function Woman(name,age){
People.call(this,anem,age) //继承父类的属性
}
Woman.prototype = new People()
Woman.prototype.constructor = Woman
let obj = new Woman('rose',21)
obj.eat()
6.寄生组合继承
通过寄生方式来修复组合继承的不足,砍掉父类的实例属性
特点:
- 只调用一次超类构造函数,效率高,避免在超类型的prototype上创建不必要的属性
- 与此同时,原型链保持不变
function People(name,age){
this.name = name || 'lisa'
this.age = age || '20'
}
//方法
Paople.prototype.eat = funciton() {
return this.name + this.age +'eat food'
}
//子类
function Woman(name,age){
People.call(this,anem,age) //继承父类的属性
}
(function(){ //创造父类方法
let super = function(){}
super.prototype = People.prototype
Woman.prototypr = new super()
})()
Woman.prototypr.constructor = Woman
let obj = new Woman()
7.ES6 继承
Class People{
constructor(name='liu',age='20'){
this.name = name
this.age = age
}
eat() {
console.log(`${this.name} ${this.age}`)
}
}
Class Woman extends People{ //继承父类
constructor(name='li',age='21'){
super(name,age) //继承父类属性
}
eat() {
super.eat() //继承父类方法
}
}
let obj = new Woman('luo')
obj.eat()