实现继承的多种方式及其优缺点

function Person(name){
    this.name = name
    this.num = function(){
        alert( this.name )
    }
}

1.原型链继承

function Child1(){
    this.name = 'one'
}
Child1.prototype = new Person()
let Child = new Child1()

// 方法:令新实例的原型等于父类实例
// 特点:1、实例可继承的属性有:实例的构造函数的属性,父类构造函数属性,父类原型的属性。(新实例不会继承父类实例的属性!)
// 缺点:1、新实例无法向父类构造函数传参。
//    2、继承单一。
//    3、所有新实例都会共享父类实例的属性。(原型上的属性是共享的,一个实例修改了原型属性,另一个实例的原型属性也会被修改!)

2.借助构造函数继承


function Child2(){
    Person.call( this , 'child2')
    this.age = 12
}
let Child = new Child2()
// 方法:使用call、apply将父类的构造函数引入子类函数
// 特点:1、只继承父类构造函数的属性,没有继承父类原型的属性
//      2、解决了原型链继承的缺点1,2,3
//      3、可以继承多个构造函数属性(call多个父类)
//      4、在子实例中可以向父实例中传参
// 缺点:1、只能继承父类构造函数的属性。
//    2、无法实现构造函数的复用。(每次用每次都要重新调用)
//    3、每个新实例都有父类构造函数的副本,臃肿。

3.组合式继承(原型链继承+构造函数继承)(常用)

function Child3(){
    Person.call( this , 'Child3')
}
Child3.prototype = new Person()
let Child = new Child3()
// 方法:结合两种模式
// 优点:1、可以继承父类原型上的属性,可以传参,可以复用
//       2、 每个新实例引入的构造函数的属性都是私有的
// 缺点:调用两次父类构造函数,消耗内存,子类的构造函数会替代原型上的父类的构造函数

4、 寄生组合式继承(常用)

// 寄生:在函数内返回一个对象,然后调用
// 组合:1、原型链继承和构造函数继承组合起来使用
function Content(obj){
    function fn(){}
    fn.prototype = obj //获取原型链上的属性
    return new fn()
}

let middle = Content( Person.prototype )

function Child(){
    Person.call(this)  //获取构造函数的属性
}

Child.prototype = middle //继承con实例,继承prototype
con.constructor = Child
let ch = new Child()
// Child的实例就继承了构造函数的属性,父类实例的属性和父类原型的属性
// 修复了组合式继承的问题
// 另一种写法
function FN(){}
FN.prototype = Person.prototype
function Child(){
    Person.call(this)
}
Child.prototype = new FN()

发布了3 篇原创文章 · 获赞 13 · 访问量 1505

猜你喜欢

转载自blog.csdn.net/weixin_44540855/article/details/104442931
今日推荐