当前位置: 首页 > Web前端 > JavaScript

学会这5种JS函数继承方式,前端面试你至少成功50%

时间:2023-03-26 20:44:39 JavaScript

摘要:函数继承是JS中比较基础和重要的部分,面试中经常被问到。下面就带大家快速了解一下JS中经常出现的必须掌握的继承方式。掌握以下内容面试几乎没问题~本文分享自华为云社区《人类高质量JS函数继承》,作者:北极光之夜。1.前言:函数继承是JS中比较基础和重要的部分,也是面试中经常被问到的。下面就带大家快速了解一下JS中经常出现的必须掌握的继承方式。掌握以下内容面试几乎没问题~2.原型链继承:原型链继承的要点是父类的实例作为子类的原型。看看下面的例子://ParentfunctionPersonfunctionPerson(name,age){//定义一些属性this.name=name;这个。年龄=年龄;this.nature=["极光","风","月亮"];}//在Person原型上定义一个方法Person.prototype.sayLove=function(){console.log(this.name+"like"+this.nature[0]);};//SubfunctionJackfunctionJack(){}//父类的实例作为子类的原型(------------------实现核心--------------------------)Jack.prototype=newPerson();现在我们创建两个Jack实例并测试是否实现了Person的继承:varjack1=newJack();varjack2=new杰克();jack2.nature[0]="海";jack1.sayLove();jack2.sayLove();控制台日志(jack1.nature);控制台日志(jack2.nature);看到运行结果确实是继承了,可以执行sayLove方法了。但是也有很多缺点。创建Jack实例时,不能传参数name和age,不同实例之间的性质引用类型属性相互影响。一改就改:3.借用构造函数继承(对象伪装):核心在于“窃取构造函数”(constructorstealing)。在子类构造函数中调用超类构造函数。因为函数毕竟是在特定上下文中执行代码的简单对象,所以您可以使用apply()和call()方法在新创建的对象的上下文中执行构造函数。它可以解决原型链继承中传递的参数和引用类型属性之间的冲突。或者只看例子://ParentfunctionPersonfunctionPerson(name,age){//定义一些属性this.name=name;这个。年龄=年龄;this.nature=["极光","风","月亮"];}//在Person原型上定义一个方法Person.prototype.sayLove=function(){console.log(this.name+"like"+this.nature[0]);};//SubfunctionLucyfunctionLucy(name,age){//通过call将this指向Lucy,相当于复制父函数Person的内容(--------实现核心--------------)Person.call(this,name,age);}//在子函数原型上定义一个方法Lucy.prototype.syaName=function(){console.log("我的名字is"+this.name);};现在我们创建两个Lucy实例并测试是否实现了Person的继承:varlucy1=newLucy("lucy1","20");varlucy2=newLucy("lucy2","22");lucy2.nature[0]="sea";console.log(lucy1.name);console.log(lucy1.nature);console.log(lucy2.nature);lucy1.syaName();lucy2.syaName();lucy1.sayLove();结果是可以继承,可以传递参数,引用类型属性互不影响,但是缺点很明显,可以看到报错报错,不能使用父类原型上的sayLove方法4.组合继承:Compositioninheritancee是结合了原型链继承和借用构造函数继承的核心实现的继承方法。它可以传递参数和引用类型属性互不影响。同时,子类也可以获得父类。类的方法。这也是目前比较常用的继承方式。直接看例子://ParentfunctionPersonfunctionPerson(name,age){//定义一些属性this.name=name;这个。年龄=年龄;this.nature=["极光","风","月亮"];}//在Person原型上定义一个方法Person.prototype.sayLove=function(){console.log(this.name+"like"+this.nature[0]);};//sub-functionLisafunctionLisa(name,age){//通过调用将this指向Lisa,相当于复制了父函数Person(-----实现核心-----------)Person.call(this,name,age);}//父类的实例作为子类的原型(------------实现核心--------------------)Lisa.prototype=newPerson();//小知识点,这里是让Lisa的构造函数再次指向Lisa,否则因为Lisa的原型是Person实例,所以构造函数会指向PersonLisa.prototype.constructor=Lisa;现在我们创建两个Lisa实例并测试是否实现了Person的继承:varlisa1=newLisa("lisa1","20");varlisa2=newLisa("lisa2","21");lisa2.nature[0]="海";控制台日志(lisa1.name);控制台日志(lisa1.nature);控制台日志(lisa2.nature);lisa1.sayLove();lisa2.sayLove();可以看到我们继承的功能基本都实现了。还修复了原型链和借用构造函数继承的缺点。不过它还是有一个小缺点,就是可以看到在代码注释实现的核心,Person被调用了两次,所以Lisa原型和实例上有两个相同的属性,所以性能上会有一定的提升浪费。5.寄生组合继承:寄生组合继承其实和组合继承类似,但是多了一个问题,解决了组合继承的原型和实例上同一个属性有两份的问题。解决方案的核心在于,由于我们只想将子类原型赋值给父类原型,所以不需要创建新的父类实例。直接新建一个对象,它的值是父类的原型,然后赋值给子类的原型。其中使用了Object.create(proto,[propertiesObject])这个方法来创建一个新的对象。相当于新对象的__proto__作为它的参数proto。当然低版本的ie可能没有Object.create,所以下面也自定义封装了Object.create方法,当然只是简单的封装。直接看例子://ParentfunctionPersonfunctionPerson(name,age){//定义一些属性this.name=name;这个。年龄=年龄;this.nature=["极光","风","月亮"];}//在Person原型上定义一个方法Person.prototype.sayLove=function(){console.log(this.name+"like"+this.nature[0]);};//子函数AndyfunctionAndy(name,age){Person.call(this,name,age);}//如果没有Object.create()方法,就简单封装一下if(!Object.create){Object.create=function(proto){functionTemp(){}Temp.prototype=proto;返回新的温度();};}//调用Object.create方法新建一对__proto__为Person.prototype的图片赋值给Andy.prototype(------实现核心------------)Andy.prototype=Object.create(Person.prototype);//修改构造函数指向Andy.prototype.constructor=Andy;现在我们创建两个Andy的实例,测试是否实现了对Person的继承:console.log(Andy.prototype.__proto__===Person.prototype);varandy1=newAndy("andy1","20");varandy2=newAndy("andy2","21");安迪2。自然[0]="海";console.log(andy1.name);控制台日志(andy1.nature);控制台日志(andy2.nature);andy1.sayLove();andy2.sayLove();完美运行:六。类继承:ES6出来了类语法糖后,可以通过类来定义类,实现类继承。直接看例子://DefineaparentclassAnimalclassAnimal{//这里构造函数指向类本身,和es5constructor(name)的行为一样{this.name=name;}likeEat(){console.log(this.name+"likeeat"+this.food);}}//定义一个子类Dog,通过extendsAnimal继承父类classDogextendsAnimal{constructor(name,food){//通过super(propertyname)继承父类属性super(name);这个。食物=食物;}likeEat(){//通过super.+父类方法实现继承父类方法super.likeEat();}}新建一个Dog实例,测试Dog是否继承自Animal:varjinmao=newDog("jinmao","bone");console.log(jinmao.name);jinmao.likeEat();可以看到已经完美实现了:7.总结:以上就是本文的全部内容,如有错误请指出~点击关注,第一时间了解华为云的新鲜技术~