1.原型继承
- 子类的原型为父类的实例,这样通过原型链即可以找到父类的属性或方法
- 缺点:由于所有的子类实例都公用的同一个原型对象,所以继承引用类型的数据也是同一个,即修改一个全部都修改,不推荐
function Father(){
this.name = "Alex"
this.colors = ["red", "blue"]
}
function Child(){
this.name = "child"
}
Child.prototype = new Father()
let p1 = new Child()
let p2 = new Child()
p1.colors.push("yellow")
p2.colors
2.构造函数继承
- 在子类里面执行父类构造函数且重新绑定this为子类
- 缺点:每个子类实例继承了父类的属性,但是没法共享到父类原型上的属性或方法-不推荐
function Father(){
this.name = "Alex"
this.colors = ["red", "blue"]
}
Father.prototype.sayHello = () => {}
function Child(){
Father.call(this)
this.name = "child"
}
let p1 = new Child()
p2.sayHello
3.混合继承
- 通过原型继承父类的方法,通过构造函数继承父类的属性,避免共享属性
- 缺点: 执行了两次父类构造函数多余的开销,第一次子类里面执行父类构造函数,第二次子类原型等于父类实例的时候
function Father(){
this.name = "Alex"
this.colors = ["red", "blue"]
}
Father.prototype.sayHello = () => {}
function Child(){
Father.call(this)
this.name = "child"
}
Child.prototype = new Father()
4.原型式继承
- 通过Object.create()方法来实现新建
- Object.getPrototype(obj)获取对象的原型对象
- Object.getOwnPropertyDescriptors(obj)
- 优点是快捷,缺点: create是浅拷贝,同样对引用类型实现共享干扰
function Father(){
this.name = "Alex"
this.colors = ["red", "blue"]
}
cosnt Child1 = Object.create(Father)
cosnt Child2 = Object.create(Father)
Child1.colors.push("yellow")
Child2.colors //["red", "blue", "yellow"]
//由于看拷贝共享的是同一个原型,所以Child1修改了,Child2也会收到干扰
5.寄生式继承
- 先拷贝一个对象,然后在次对象上扩展,最终返回次对象,就像新对象寄生在父类一样
- 优点是可以随意扩展子类,缺点是浅拷贝,依旧存在数据共享干扰的问题
function Clone(obj){
cosnt obj2 = Object.create(obj)
obj2.sayBey = () => {}
return obj2
}
6.寄生组合继承-推荐
- 通过寄生只浅拷贝父类原型-继承父类原型上的方法或属性
- 通过构造函数继承父类属性,避免共享干扰
function clone(father, child){
const proto = Object.getPrototype(father)
child.prototype = Object.create(proto)
child.prototype.constructor = child
}
function Father(){
this.name = "Alex"
this.colors = ["red", "blue"]
}
Father.prototype.sayHello = () => {}
function Child(){
Father.call(this)
this.name = "child"
}
clone(Father, Child)
Child.prototype.sayBey = () => {}
const p1 = new Child()
7.ES6,extends继承
Class Child extends Father {
constructor(name){
super(name)
}
}