2024年最全第二章 面向对象编程之继承(1),2024年最新教资面试题

总结

前端资料汇总

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

  • 框架原理真的深入某一部分具体的代码和实现方式时,要多注意到细节,不要只能写出一个框架。

  • 算法方面很薄弱的,最好多刷一刷,不然影响你的工资和成功率😯

  • 在投递简历之前,最好通过各种渠道找到公司内部的人,先提前了解业务,也可以帮助后期优秀 offer 的决策。

  • 要勇于说不,对于某些 offer 待遇不满意、业务不喜欢,应该相信自己,不要因为当下没有更好的 offer 而投降,一份工作短则一年长则 N 年,为了幸福生活要慎重选择!!!
    喜欢这篇文章文章的小伙伴们点赞+转发支持,你们的支持是我最大的动力!

instance2.getName()

instance2.getTime()

在这里插入图片描述

分析一下instance的构造:

在这里插入图片描述

组合继承模式将类式继承和构造函数式继承相结合,可以看到构造函数式继承将父类的属性复制到子类(每次执行构造函数式继承,相当于重新new一个父类实例,所以不会有相互覆盖的可能),但是不涉及到protype,所以不会继承父类的原型方法。所以接下来马上使用类式继承,将父类的实例赋值给子类的prototype,因为子类原型prototype上继承父类的共有属性(比如books)和之前子类执行构造函数时生成的books属性同名,所以instance.books不会取原型链上的books属性,但是能够取到原型链上的父类原型pototype上的方法。

综上,组合继承完美结合了类式继承和构造函数式继承的优点,并且消除了他们的缺点。但是这种继承也不是完全没有缺点,就是执行了2遍的父类构造函数。

那有没有办法只执行1遍父类的构造函数,以减少消耗呢?

方法肯定是有的,那就是使用终结继承大法——寄生组合式继承!

终极继承大法——寄生组合式继承


原型式继承——封装类式继承

在说明终极继承大法之前,我们先学习一下它的组成之一,原型式继承。

function inheritObject(o){

// 声明一个过渡函数对象

function F(){}

// 过渡对象的原型继承父对象

F.prototype = o

// 返回过渡对象的一个实例,该实例的原型继承了父对象

return new F()

}

可以看出原型式继承和类式继承十分相似,实际上它就是类式继承的一个封装。只不过这里的子类是以过渡对象的形式出现的。

寄生式继承——原型式继承的二次封装

// 声明基对象

var book = {

name:‘js book’,

alikeBook:[‘css book’,‘html book’]

}

// 原型式继承

function inheritObject(o){

// 声明一个过渡函数对象

function F(){}

// 过渡对象的原型继承父对象

F.prototype = o

// 返回过渡对象的一个实例,该实例的原型继承了父对象

return new F()

}

// 寄生式继承

function createBook(obj){

// 通过原型式继承创建新对象

var o = new inheritObject(obj)

// 扩展新对象

o.getName = function(){

console.log(this.name)

}

return o

}

var newBook = new createBook(book)

在这里插入图片描述

寄生式继承其实就是对实例化后的原型继承对象进行扩展。

寄生组合式继承——终极

// 原型式继承

function inheritObject(o){

// 声明一个过渡函数对象

function F(){}

// 过渡对象的原型继承父对象

F.prototype = o

// 返回过渡对象的一个实例,该实例的原型继承了父对象

return new F()

}

// 寄生组合式继承

function inheritPrototype(subClass,superClass){

// 复制一份父类的原型副本保存在变量中

var p = inheritObject(superClass.prototype)

// 修正因为重写子类原型导致子类的constructor属性被修改

p.constructor = subClass

subClass.prototype = p

}

// 定义父类

function SuperClass(name){

this.name = name

this.colors = [‘#000000’,‘#ffffff’,‘#000fff’]

}

// 定义父类原型方法

SuperClass.prototype.getName = function(){

console.log(this.name)

}

// 定义子类

function SubClass(name,time){

// 构造函数式继承

SuperClass.call(this,name)

// 子类新增属性

this.time = time

}

// 寄生式继承父类原型

inheritPrototype(SubClass,SuperClass)

// 子类新增原型方法

SubClass.prototype.getTime = function(){

console.log(this.time)

}

// 创建2个测试方法

var instance1 = new SubClass(‘js book’,2021)

var instance2 = new SubClass(‘css book’,2022)

instance1.colors.push(‘red’)

console.log(instance1.colors)

console.log(instance2.colors)

instance2.getName()

instance2.getTime()

在这里插入图片描述

分析下instance1的结构:

在这里插入图片描述

寄生组合式继承替换掉类式继承,与构造函数式继承的结合堪称完美。首先构造函数式继承复制了父类的共有属性,然后寄生组合式继承只是将父类的原型prototype复制到了子类的prototype,并且还修正了子类constructor属性。

多继承


JavaScript不是只有一条原型链吗?怎么实现多继承呢?我们来看下下面的一段代码:

在这里插入图片描述

通过extend方法,我们成功将source中的属性成功复制到了target对象中,但是仅仅这样还不够,会出现几个问题:

1)如果target中有相同的属性,就会被source所覆盖

2)如果source中的某个属性是引用类型,就会导致target复制的该属性指向同一地址

3)extend方法没有涉及到prototype

解决这几个问题后,我们再考虑多继承的问题,不过是将source变成多个而已。

在这里插入图片描述

到这里,发现自己手写了一个深拷贝,解决了前2个问题,那prototype的问题呢?考虑到多继承和单继承不同,在此不做讨论,如果prototype也需要继承的话,可以参考extend方法。

接下来,我们需要扩展extend方法,将复制一个对象转为复制多个对象的属性。

  • 26
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值