js继承的几种方式

JS中的继承(上).md
JS中的继承(下).md

  1. 原型链继承
// 父类
function Person() {}

// 子类
function Student(){}

// 继承
Student.prototype = new Person()

我画张图就很容易理解了, (画错了, 最下边两个应该是Student实例)
在这里插入图片描述

缺点, 共享prototype上的属性,如果是引用类型, 就会造成多个实例共享该属性, GG

  1. 构造函数继承
// 父类
function Person(name) {
  this.say = function() {}    // 改动的代码
}
// 子类
function Student(name){
    Person.call(this,name)
}

在Student中调用父类构造函数, 因为父类前面没有用new, 所以只是简单执行, 然后把this指向了student实例, 相当于

// 父类
function Person(name) {
  this.say = function() {}    // 改动的代码
}
// 子类
function Student(name){
    this.say = function() {}    // 父类构造函数里面的代码
}

所以该模式叫借用构造函数模式
缺点:每实例化一个子类, 就要执行一次父类的构造函数, 所以子类所有实例上相同的属性都是拷贝值

  1. 组合继承
// 父类
function Person() {
  this.hobbies = ['music','reading']
}
// 父类函数
Person.prototype.say = function() {console.log('I am a person')}
// 子类
function Student(){
    Person.call(this)             // 构造函数继承(继承属性)
}
// 继承
Student.prototype = new Person()  // 原型链继承(继承方法)

缺点: 父类构造函数里面的代码会执行2遍
把共享方法挂在父类构造函数里, 方便拷贝值而不互相影响, 把共享方法定义在父类构造函数上, 用原型方式继承

  1. 原型式继承
    该方式其实是根据一个已有的实例去继承, 将该实例或该实例的原型作为原型
function clone (proto) {
    function F () {}
    F.prototype = proto
    return new F()
}

function Parent(){
	this.arr = [1,2,3]
}

let obj = new Parent()

let aa = clone(obj)
let bb = clone(obj)

aa.length = 4
console.log(bb.arr) // [1,2,3,undefined]

看图,
参数可以传入一个对象, 相当于情况1, 情况1跟原型链继承是类似的
如果传入的是原型对象, 相当于情况2, Object.create(xx.prototype)

缺点, 也会造成引用属性共享
在这里插入图片描述
5. 寄生式继承
寄生式继承其实就是在原型式继承的基础上,做了一些增强.
跟构造函数模式一样, 实例对象的引用类型属性无法共享, say方法会在每个实例上创建一次

function cloneAndStrengthen(proto){
    function F () {}
    F.prototype = proto
    let f = new F()
    f.say = function() { 
        console.log('I am a person')
    }
    return f
}
  1. 寄生组合式继承
    寄生组合式继承就是为了降低组合模式中, 调用父类构造函数的开销而出现的

其背后的基本思路是: 不必为了指定子类型的原型而调用超类型的构造函数

寄生组合式到底有什么优点?为什么要新建一个F函数, 再创建F的实例?先看图:
在这里插入图片描述
回想组合式继承, 会执行两次父类构造函数
第一次是将子类的原型指向父类的实例
第二次是子类实例化的时候, 借用了父类的构造函数

寄生组合为什么要新建一个F构造函数,再将Child的原型指向F实例?
个人理解继承组合和组合继承有不同的使用场景, 在于组合继承,子类会带有父类构造函数中this给的方法、属性, 而寄生组合继承, 拿的是F的实例,而F和Parent不同在于F是个空函数

function inherit(sub, super){
    let prototype = clone(super.prototype)
    // function F () {}
    // F.prototype = proto
    // return new F()
    prototype.constructor = sub    
    sub.prototype = prototype      
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值