原型链继承
原理:将父类的实例指向子类的原型
缺点:牵一发而动全身,因为共享同一个原型,所以父类原型的修改会直接影响子类,且任一子类的修改也会影响其他子类
function Parent(name){
this.name = name
}
Parent.prototype.age = '55'
function Son(){
this.name = "Mike"
}
Son.prototype = new Parent()
var son = new Son()
console.log(son.age) // 55
console.log(son instanceof Parent) // true
构造函数继承
原理:复制父类的实例给子类
缺点:不能实现函数复用
function Parent(name){
this.name = name
}
Parent.prototype.age = '55'
function Son(){
Parent.call(this, 'son')
this.age = '27'
}
var son = new Son()
console.log(son.name) // son
console.log(son.age) // 27
console.log(son instanceof Parent) // false
组合式继承
原理:原型链继承+构造函数继承
缺点:需要调用两次父类,子级的调用覆盖了原型调用
function Parent(name){
this.name = name
console.log("调用父级") // 调用父级 * 2
}
Parent.prototype.age = '55'
function Son(name){
Parent.call(this, name)
this.age = '27'
}
Son.prototype = new Parent()
var son = new Son('Alice')
console.log(son.name) // Alice
console.log(son.age) // 27
console.log(son instanceof Parent) // true
实例继承
原理:给父类的实例添加属性和方法,作为子类返回
function Parent(name){
this.name = name
}
function Son(args){
var instance = new Parent(args)
instance.age = '27'
instance.sleep = function(){
console.log('sleep')
}
return instance
}
var son = new Son('Tom')
console.log(son.name) // Tom
console.log(son.age) // 27
console.log(son instanceof Parent) // true
原型式继承
ES5 通过新增 Object.create()方法规范化了原型式继承,此方法可以接受两个参数,第一个参数最为新对象原型的对象 和一个为新对象定义额外属性的对象.
原理:借助原型基于已有的对象创建新的对象
缺点:和原型链继承相似,牵一发而动全身
function object( O ){ // 传递一个字面量函数
function F(){} // 创建一个构造函数
F.prototype = O // 将字面量函数赋值给构造函数的原型
return new F() // 返回构造函数的实例
}
寄生式继承
原理:(基于原型式继承+工厂模式)创建一个用于封装继承过程的函数,在函数通过某种方式增强这个对象,最后将这个对象返回
缺点:原型继承存在的缺点他都存在
使用寄生式继承为对象添加方法,会由于不能做到方法的复用而降低效率,这一点和构造函数模式类似
function object(o){
function F(){}
F.prototype = o
return new F()
}
function createAnother(original){
var clone = object(original) // 调用函数创建一个新的对象
clone.fn = function(){} // 增强这个对象
return clone // 返回这个对象
}
寄生组合式继承
原理:构造函数继承+创建子类和父类的链接
function SuperType(name){
this.name = name
this.colors = ['red','green','yellow']
}
SuperType.prototype.sleep = function(){ alert('prototype') }
function SubType(name,age){
SuperType.call(this,name)
this.age = age
}
function inherit(SubType,SuperType){
var proto = SuperType.prototype
proto.constructor = SubType
SubType.prototype = proto
}
inherit(SubType,SuperType)
圣杯模式
let inherit = (function(){
function F(){} //函数是一个闭包,仅用做一个缓冲而不做他用
return function(son,parent){
F.prototype = parent.prototype
// son.prototype = F.prototype; /* 不能这么写,因为这样写就相当于对象son、parent和 F 共享原型了 */
son.prototype = new F()
// 使对象targetSon试图修改自身属性时仅仅是以buffer函数作为对象进行修改,而不会影响到其他对象
son.prototype.uber = parent.prototype
son.prototype.constructor = son
}
})()
ES6 class继承
注:一定要有super,否则新建实例时会报错。因为子类没有自己的this对象,需要继承父类的this对象,如果没有super子类就得不到父类的this对象
class Parent{
constructor(props){
this.name = props.name || 'Unknown'
}
eat(){
console.log(this.name + '会来吃东西')
}
}
class Son extends Parent{
constructor(props,myAttribute){
super(props)
this.type = props.type
this.attr = myAtrribute
}
play(){
console.log('子类的私有方法')
}
myattr(){
console.log('子类的自由方法二')
}
}