每天一点面试题(5) -------原型继承部分

对于原型继承 快到0202年了 基本已经用的很少了 但是在源码中还有很多需要实现底层构架的情况下还是会用到 所以一定要学好这部分 虽然学好了不常用也会忘记
说到继承必须说原型 所以原型部分会在JS分类里写清楚

想要继承,就必须要提供个父类(继承谁,提供继承的属性)
在这里插入图片描述

一. 原型继承

在这里插入图片描述
重点:让新实例的原型等于父类的实例。
特点:1、实例可继承的属性有:实例的构造函数的属性,父类构造函数属性,父类原型的属性。(新实例不会继承父类实例的属性!)
缺点:1、新实例无法向父类构造函数传参。
   2、继承单一。
   3、所有新实例都会共享父类实例的属性。(原型上的属性是共享的,一个实例修改了原型属性,另一个实例的原型属性也会被修改!)

二. 构造函数继承

在这里插入图片描述
重点:用.call()和.apply()将父类构造函数引入子类函数(在子类函数中做了父类函数的自执行(复制))

特点:1、只继承了父类构造函数的属性,没有继承父类原型的属性。
   2、解决了原型链继承缺点1、2、3。
   3、可以继承多个构造函数属性(call多个)。
   4、在子实例中可向父实例传参。
缺点:1、只能继承父类构造函数的属性。
2、无法实现构造函数的复用。(每次用每次都要重新调用)
   3、每个新实例都有父类构造函数的副本,臃肿。

三. 组合继承(组合原型链继承和借用构造函数继承)(常用)

在这里插入图片描述
重点:结合了两种模式的优点,传参和复用
特点:1、可以继承父类原型上的属性,可以传参,可复用。
   2、每个新实例引入的构造函数属性是私有的。
缺点:调用了两次父类构造函数(耗内存),子类的构造函数会代替原型上的那个父类构造函数。

四. 原型式继承

在这里插入图片描述重点:用一个函数包装一个对象,然后返回这个函数的调用,这个函数就变成了个可以随意增添属性的实例或对象。object.create()就是这个原理。
特点:类似于复制一个对象,用函数来包装。
缺点:1、所有实例都会继承原型上的属性。
   2、无法实现复用。(新实例属性都是后面添加的)

五. 寄生式继承

在这里插入图片描述重点:就是给原型式继承外面套了个壳子。
优点:没有创建自定义类型,因为只是套了个壳子返回对象(这个),这个函数顺理成章就成了创建的新对象。
缺点:没用到原型,无法复用。

六. 寄生组合式继承(常用)

寄生:在函数内返回对象然后调用
组合:1、函数的原型等于另一个实例。2、在函数中用apply或者call引入另一个构造函数,可传参 
在这里插入图片描述
在这里插入图片描述
重点:修复了组合继承的问题

七. 多态继承

简单来说就是让 一个类去继承多个实例 也会单独写一篇学习文章

八. 在你不知道的JS中这样说的

通常被称作的原型继承机制,a可以“继承” Foo.prototype并访问 Foo.prototype的myName()函数。但是之前只是把继承看作是类和类的关系,并没有把它看作是类和实例之间的关系
在这里插入图片描述上图不仅展示出对象()实例a1到Foo.prototype的委托关系,还展示出Bar.prototype到Foo.prototype的委托关系,而后者和类继承很相似,只有箭头的方向不同。箭头表明是委托关联不是复制操作。
原型风格的代码

function Foo(name) {
    this.name = name
}
Foo.prototype.myName = function() {
    return this.name
}
function Bar(name, lable) {
    Foo.call( this, name )
}
//我们创建了一个新的Bar.prototype对象并关联到Foo.prototype
Bar.prototype = Object.create( Foo.prototype )
//注意!  现在没有Bar.prototype 对象并关联到 Foo.prototypr
//如果需要这个属性的话可能需要手动修复一下
Bar.prototype.myLabel = function() {
    return this.lable
}
let a = new Bar( "a", "obj a" )

a.myName();    // "a"
a.myLabel();   // "obj a"

这段代码的核心是Bar.prototype = Object.create( Foo.prototype )
调用Object.create(。。。)会凭空创建一个“新”对象内部的[[Prototype]]关联到指定对象
这样做的唯一缺点是需要创建一个新对象然后把旧对象抛弃掉,不能直接修改已有默认对象。

es6添加了辅助函数 Object.setPrototypeOf(…),可以用标准且可靠的方法来修改关联。
对比一下:

//ES6之前需要抛弃默认的Bar.prototype
BarProp.prototype = Object.create(Foo.prototype)
//ES6之后可以直接更改
Object.setPrototypeOf( Bar.prototype, Foo.prototype )
发布了38 篇原创文章 · 获赞 1 · 访问量 558

猜你喜欢

转载自blog.csdn.net/weixin_43718291/article/details/103275423