当前位置: 首页 > 科技观察

前端实现继承的几种方式

时间:2023-03-14 01:07:59 科技观察

1.原型链继承构造函数、原型和实例之间的关系:每个构造函数都有一个原型对象,原型有一个指向构造函数的属性,实例有一个内部指向原型的指针。原型链的基本思想:如果原型是另一个类型的实例怎么办?这意味着原型本身有一个指向另一个原型的内部指针,而这个原型又有一个指向另一个构造函数的指针。这在实例和原型之间构造了一个原型链。重点:使新实例的原型等于父类的实例。functionSuperType(){this.property=true}SuperType.prototype.getSuperValue=function(){returnthis.property}functionSubType(){this.subproperty=false}//继承SuperTypeSubType.prototype=newSuperType()SubType。prototype.getSubValue=function(){returnthis.subproperty}letinstance=newSubType()console.log(instance.getSuperValue())//true复制代码特点:实例的可继承属性有:实例构造函数的属性,parentclassconstructorattribute,父类原型的属性。缺点:new实例不能给父类构造函数传递参数。单一继承。(只能继承一个父类构造函数)所有的新实例都会共享父类实例的属性。(原型上的属性是共享的,如果一个实例修改了原型属性,那么另一个实例的独创性也会被修改!)要给子类原型添加属性和方法,必须使用像newSuperType()这样的语句,然后执行代码如下:functionSuperType(){this.colors=["red","blue","green"]}functionSubType(){}//InheritSuperTypeSubType.prototype=newSuperType()letinstance1=newSubType()instance1.colors.push("black")console.log(instance1.colors)//"red,blue,green,black"letinstance2=newSubType()console.log(instance2.colors)//"red,blue,green,black》复制代码2.借用构造函数的继承要点:使用.call()和.apply()将父类构造函数引入子类函数中(父类函数在子类函数中自执行)subclassfunction(copy))functionSuperType(name){this.name=name}functionSubType(){//继承SuperType并传参SuperType.call(this,"Nicholas")//实例属性this.age=29}letinstance=newSubType()console.log(instance.name)//"Nicholas";console.log(instance.age)//29Copycodefeatures:only继承父类构造函数的属性,而不是父类原型的属性。解决原型链继承的缺点1、2、3。可以继承多个构造函数属性(调用多个)。在子实例中,可以将参数传递给父实例。解决了引用值的问题缺点:只能继承父类构造函数的属性。无法实现构造函数的重用。每个新实例都有一个父类构造函数的副本,臃肿。3.组合继承(组合原型链继承和借用构造函数继承)(常用)重点:结合两种模式的优点,传递参数和复用函数SuperType(name){this.name=namethis.colors=["red","blue","green"]}SuperType.prototype.sayName=function(){console.log(this.name)}functionSubType(name,age){//继承属性SuperType.call(this,name)////第一次调用SuperType()this.age=age}//继承方法SubType.prototype=newSuperType()//第二次调用SuperType()SubType.prototype.sayAge=function(){console.log(this.age)}letinstance1=newSubType("Nicholas",29)console.log("instance1=>",instance1)instance1.colors.push("black")console.log(instance1.colors)//"red,blue,green,black"instance1.sayName()//"Nicholas";instance1.sayAge()//29letinstance2=newSubType("Greg",27)console.log(instance2.colors)//"red,blue,green"instance2.sayName()//"Greg";instance2.sayAge()//27复制代码特点:可以继承父类原型的属性,可以传递参数,可以复用。每个新实例引入的构造函数属性都是私有的。缺点:组合继承其实存在效率问题。主要的效率问题是父类构造函数总是会被调用两次:一次是在创建子类原型时,一次是在调用子类构造函数时。四、原型继承的重点:用一个函数包裹一个对象,然后返回到这个函数的调用,这个函数就变成了一个可以随意添加属性的实例或对象。object.create()是原理。//核心代码functionobject(o){functionF(){}F.prototype=oreturnnewF()}letperson={name:"Nicholas",friends:["Shelby","Court","Van"],}letanotherPerson=object(person)anotherPerson.name="Greg"anotherPerson.friends.push("Rob")letyetAnotherPerson=object(person)yetAnotherPerson.name="Linda"yetAnotherPerson.friends.push("芭比娃娃")console.log(person.friends)//"Shelby,Court,Van,Rob,Barbie"复制代码特点:类似于复制一个对象,然后用函数包裹起来。缺点:所有实例都会继承原型上的属性。无法实现复用。(后面会增加新的实例属性)原型继承非常适合不需要创建单独的构造函数,但仍然需要在对象之间共享信息的情况。但请记住,属性中包含的引用值将始终在相关对象之间共享,这与使用原型模式相同。functionobject(o){functionF(){}F.prototype=oreturnnewF()}functioncreateAnother(original){letclone=object(original)//通过调用函数创建一个新对象clone.sayHi=function(){//以某种方式增强这个对象console.log("hi")}returnclone//返回这个对象}letperson={name:"Nicholas",friends:["Shelby","Court","Van"],}letanotherPerson=createAnother(person)anotherPerson.sayHi()//"hi"//寄生继承也适用于主要关注对象而不是类型和构造函数的场景。寄生继承不需要object()函数,任何返回新对象的函数都可以在这里使用。//注意通过寄生继承给对象添加函数会导致函数难以复用,类似于构造函数模式。复制代码的优点:没有创建自定义类型,因为它只是一个返回对象(this)的壳,而这个函数自然成为一个新创建的对象。缺点:没有使用原型,不能复用。6、Parasiticcombinedinheritance(常用)要点:通过借用构造函数来继承属性,但是使用的是混合原型链继承方式。其基本思想不是通过调用父类构造函数给子类原型赋值,而是获取父类原型的副本。说到底,就是利用寄生继承,继承父类的原型,然后将返回的新对象赋值给子类的原型。寄生:在函数内部返回对象然后调用组合:函数的原型等于另一个实例。使用apply或者call在函数中引入另一个构造函数,可以传参functionobject(o){functionF(){}F.prototype=oreturnnewF()}/*functioninheritPrototype(subType,superType){let原型=对象(superType.prototype);//创建对象prototype.constructor=subType;//增强对象subType.prototype=prototype;//分配对象}*/functionSuperType(name){this.name=namethis.colors=["red","blue","green"]}SuperType.prototype.sayName=function(){console.log(this.name)}functionSubType(name,age){SuperType.call(this,name)this.age=age}letprototype=object(superType.prototype)//创建对象subType.prototype=prototype//分配对象原型.constructor=subType//修复实例//inheritPrototype(SubType,SuperType);SubType.prototype.sayAge=function(){console.log(this.age)}重复代码优先:修复了组合继承问题缺点:实现麻烦头条号。github:https://github.com/zuopf769