经典面试题第五更---带你搞清JS继承原理

前言:
    🤡 作者简介:我是Morning,计算机的打工人,想要翻身做主人 🙈 🙈 🙈
    🏠 个人主页:  Morning的主页
    📕系列专栏:前端面试备战  
    📞 如果小编的内容有欠缺或者有改进,请指正拙著。期待与大家的交流
    🔥如果感觉博主的文章还不错的话,👍点赞👍 + 👀关注👀 + 🤏收藏🤏

目录

原型链继承:

构造函数继承:

 组合式继承:

寄生组合式继承

ES6 Class继承


面试题:你能提一提JS的有关继承么

就需要讲一讲以下的几种继承,将红色字体阐述出来

原型链继承:

让子类的原型指向父类的实例

function Father(){
    this.money=30000,
    this.arr=[1,2,3]
}
Father.prototype.getMoney=function(){
    return `获得了${this.money}`
}
function Son(){}
//子类的原型指向父类的实例  
Son.prototype=new Father()
const bigSon=new Son()
console.log(bigSon.money);//30000
console.log(bigSon.getMoney());//获得了30000

const smallSon=new Son()
smallSon.arr.push(5)
console.log(smallSon.arr); //[1, 2, 3, 5]
console.log(bigSon.arr); //[1, 2, 3, 5]

 弊端:

<1.>因为只有一个父类的实例作为他们的原型,所以所有实例共享了一个原型上的属性arr,当原型上的属性作为引用类型时,此处是数组,smallSon添加一个新内容会导致bigSon上的arr也改变了。

<2>.子类构造函数不能传递参数到父类原型上。

构造函数继承:

在子类的构造函数中,执行父类的构造方法,并且绑定子类的this(这也是call的实战应用之一,在之后的文章中我会出一期专门来介绍call)

function Father(money){
    this.money=[money]
}
function Son(money){
    Father.call(this,money)
}
const son1=new Son(10000)
const son2=new Son(20000)
console.log(son1.money,son2.money); //[10000],[20000]
//弊端

//继承不到父类的原型上的属性与方法
Father.prototype.getMoney=function(){
    return `获得了${this.money}`
}
Father.prototype.galary=4000
console.log(son1.galary); //undefined
console.log(son1.getMoney()); //ncaught TypeError: son1.getMoney is not a function

弊端:

<1>.继承不到父类的原型上的属性与方法

<2>.两个实例对象都拥有了拷贝来的money属性,所以没有共享属性。但同时也意味着创造一个实例就得拷贝一次父类的所有属性。且因为不能继承父类原型,所以方法不能复用,被迫拷贝方法。

 组合式继承:

结合了原型链继承和构造函数继承

function Father(money){
    this.money=[money]
}
function Son(money){
    Father.call(this,money)第二次调用父类构造函数
}
Son.prototype=new Father()//第一次调用父类构造函数

const son1=new Son(10000)
const son2=new Son(20000)
console.log(son1.money,son2.money); //[10000],[20000]
//可以继承父类的原型上的属性与方法
Father.prototype.getMoney=function(){
    return `获得了${this.money}`
}
Father.prototype.galary=4000
console.log(son1.galary); //4000
console.log(son1.getMoney()); //获得了10000

弊端:每一次创建子类实例都会调用两次父类构造函数,降低性能

寄生组合式继承

要改动的代码:

Son.prototype=new Father()//第一次调用父类构造函数
//更改为
Son.prototype=Father.prototype

但如果将父类原型赋值给子类原型的话,在子类原型上添加方法、属性,相应父类上也会添加

function Father(money){
    this.money=[money]
}
function Son(money){
    Father.call(this,money)
}
Son.prototype=Father.prototype
//在子类原型上添加属性、方法
Son.prototype.fee=[3000]
Son.prototype.getGalary=function(){
    console.log('这是子类的方法');
}
var father=new Father()
father.getGalary()//这是子类的方法
console.log(father.fee);//[3000]

其实子类的原型应该为父类的原型的深拷贝 

function Father(money){
    this.money=[money]
}
function Son(money){
    Father.call(this,money)
}
Son.prototype=Object.create(Father.prototype)
//在子类原型上添加属性、方法
Son.prototype.fee=[3000]
Son.prototype.getGalary=function(){
    console.log('这是子类的方法');
}
var father=new Father()
console.log(father.fee);//undefined
father.getGalary()//报错,father.getGalary is not a function

ES6 Class继承

以上的继承方式都是通过原型去解决的。在ES6中,我们可以使用class去实现继承,并且实现起来很简单

class Parent{
    constructor(value){
        this.val=value
    }
    getValue(val){
        console.log(this.val);
    }
}
class Children extends Parent{
    constructor(value){
        super(value)
        this.val=value
    }
}
let child=new Children(1)
child.getValue() //1
console.log(child instanceof Parent); //true

class实现继承的核心在于使用extends表明继承来自哪个父类,并且在子类的构造函数中必须调用super。这段代码可以看成Parent.call(this,value) 

更加具体的class继承大家可以看看此篇文章ES6 | 关于class类 继承总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

苏茂林别干饭了

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值