手机版

历史上最详细的javascript继承(推荐)

时间:2021-08-24 来源:互联网 编辑:宝哥软件园 浏览:

前言

让我们分享js中最常见和最详细的继承方法。接下来,我们将展示以下维度,以显示文章有点长。请耐心阅读。如有误解,希望留言指出

生成原因代码,实现基本原理,实现场景的优缺点,继承方式

原型链继承借用构造器模式继承组合继承原型继承寄生继承寄生组合原型链继承我相信我所有的朋友都知道原型链继承(ECMAScript描述了原型链的概念,并以原型链作为实现继承的主要方法),因为原型链继承非常强大,但它也有其缺点。接下来,让我们看看原型链继承到底是基于以上维度的:(完成一个原型链继承需要两个构造函数)

//SuperType构造函数称为超类functionsupertype () {this。名称=' superthis . friend=[];this.property=true} SuperType . prototype . GetName=function(){ return this . name;} SuperType . prototype . GetSuperVaLue=function(){ return this . property;};//SubType构造函数称为subclass functionsubtype (name,age) {this。name=namethis.age=年龄;this.subproperty=false} subtype . prototype=new SuperType();SubType . prototype . constructor=SubType;subtype . prototype . GetAge=function(){ return this . age;} subtype . prototype . getsubvalue=function(){ return this . subproperty;};var child=new SubType('shiny ',12);console . log(child . getname)//shinyconsole . log(child . getage())//12说明了一些属性

基本的

使用类似于继承搜索范围的原型链

语言实现

定义了两个构造函数,分别是SuperType和SuperType。为了实现子类,可以使用父类的属性(自身和原型上的属性)。重写子类的原型指向父类实例,这样子类的构造函数就是父类的实例地址,子类可以利用父类本身的属性和原型来实现

优势

子类可以通过原型链的搜索来实现父类的公共属性和子类的实例

劣势

操作一些参考数据会有问题。两个实例将共享继承实例的引用数据类,并仔细定义方法,以避免定义的方法也继承对象原型的方法。父构造函数不能直接使用参数借用构造函数模式继承。原型链继承虽然很强大,但也有它的缺点。借用构造函数继承可以解决原型链继承的缺点。实现了明线面的解释代码:

//使用函数SuperType.call(this,name) {this。name=namethis。friend=['a ',' b']} supertype。原型。getfriend=function(){返回这个。fire}函数子类型(名称){//来执行父函数超类型。调用(。} var child=new SubType(' shiny ')var child red=new SubType(' red ')console . log(child . name)//shinyconsole . log(child red . name)//redchild . firend . push(' c ')console . log(child . friend)//a,b,cconsole . log(children . friend)//a,bconsole . log(children . getfriend)//未定义的基本原则

使用调用apply方法,通过执行方法修改tihs (context),使父类的这个变成子类实例的这个,这样每个实例都会得到父类的属性,实现引用属性的备份

使用场景

父类中的一些子类需要使用共享引用类型,子类可以操作父类的共享引用类型,但是不能使用父类的非此绑定属性和方法(放入父类原型的属性和方法)

语言实现

不要将父类中的一个构造函数视为一个函数。比较容易理解。借用子类的构造函数来修改它,这样子类的实例就包含了父类的属性

优势

解决了原型链继承的引用类型操作问题,解决了父类传递参数的缺点

仅仅使用借用的构造函数模式来继承是无法去掉足够多的函数的。方法定义了构造函数中的重用。超类的原型定义方法不适用于子类。子类的实例只获取父类绑定的属性。考虑到这些缺点,单独借用构造函数很少被用作组合继承

以上两种继承方式(原型链继承借用构造函数继承)各有优缺点,但并不完美。下面我们来解释组合遗传

代码实现:

函数SuperType(name){ this . name=name;this.firend=['a ',' b ']} SuperType . prototype . GetNAmE=function(){ return this . name } function SubType(name,age){ this . age=age;SuperType.call(this,name)} subtype . prototype=new SuperType();SubType . prototype . constructor=SubType;SubType . prototype . GetAge=function(){ return this . age } var child shiny=new SubType(' shiny ',23);var child ReD=new SupLe(' red ',22);childshiny . firend . push(' c ');child red . firend . push(' d ');console . log(child shiny . getname());console . log(child shiny . Getage());console . log(childred . getname());console . log(childred . Getage());console . log(child red . friend);//[a,b,d]console . log(child shiny . friend);//[a、b、c]基本原则

利用原型链的继承实现,通过原型搜索功能、借用构造函数方法和使用实例备份父类共享引用类型备份来满足原型链共享方法

使用场景

获得原型链继承和构造函数继承的优点是开发人员公认的继承方法,但在语言实现上也有其缺点

定义了两个构造函数,分别是SuperType和SuperType。为了实现子类,可以使用父类的属性(自身和原型上的属性)。重写子类的原型以指向父实例,这样子类的构造函数就是父类的实例地址。要实现子类,可以使用父类本身和原型的属性。不要将父类中的某个函数视为构造函数。比较容易理解。在子类的构造函数中,通过修改来借用父函数来执行,这样子类实例就包含了父类的属性。

优势

解决了原型链继承引用类型的实例操作导致引用改变的问题,解决了构造函数继承方式可以使用父原型子类实例的缺点

父类的构造函数被实例替换两次。父类的构造函数会有一些这样的属性,子类的构造函数也会有一些属性的原型继承

换句话说,上面的组合继承不是被开发者认可了吗?什么是原型继承?让我们看看原型继承是什么样子的。

代码实现:

1函数对象(o){函数F(){ };f .原型=o;return new F()} var person={ name : ' Nicholas ',friends 3360[' Shelby ',' Court ',' Van ']};var personShiny=对象(人);var personRed=对象(人);console . log(personshiny . name)//Nicholascon sole . log(personRed . name)//Nicholasensonshiny . friends . push(' red ');personRed.friends.push('闪亮');console . log(personshiny . friends)//[' shelby ',' court ',' van ',' red ',' shiny']//ecmascript5通过添加Object.create()方法来标准化原型继承。此方法接收两个参数:一个//用作新对象原型的对象,以及(可选)为新对象定义附加属性的对象。传入参数时,//Object.create()的行为与Object()方法相同。2 var person={name: 'Nicholas ',friends 3360[' Shelby ',' Court ',' Van ']};var personShiny=object . create(person);var personard=object . create(person);console . log(personshiny . name)//Nicholascon sole . log(personRed . name)//Nicholasensonshiny . friends . push(' red ');personRed.friends.push('闪亮');console . log(Person shing . friends)//[' Shelby ',' Court ',' Van ',' Red ',' shing ']基本原则

通过Object.create()方法创建一个带有基类的实例,这个实例的__proto__指向基类

使用场景

不使用构造函数,您只想保持一个对象与另一个对象相似

语言实现

需要创建一个基本对象作为新对象的基本对象,并通过object方法或Object.create方法获取一个新实例。这个新实例上的__proto__指向基本对象

优势

实现了原型链继承,不需要创建构造函数,代码量减少了一部分

劣势

一些参考数据操作会导致问题。两个实例会使用继承实例的引用数据类谨慎定义方法,避免定义方法的方法也继承同名的对象原型,不能直接对父构造函数使用参数寄生继承

让我们看看上面的原型继承。其实和原型链继承没有太大区别,只是省略了构造函数。然而,原型继承也有缺点(它不能向备份的对象添加属性)。下面是寄生继承来解决它。

代码实现:

//非常类似于工厂模式,创建一个对象,增强一些函数并返回对象函数创建另一个(o){ var clone=object(o);clone . SayHi=function(){ console . log(' hi ')} return clone } var person={ name : ' shiny ',friends 3360[' a ',' b ']} var person shiny=create other(person);console . log(personshiny . sayhi())//ho基本原理

备份对象,向备份的对象添加属性,然后返回

使用场景

要在不使用构造函数的情况下实现继承,前面的继承模式演示中使用的object()函数是不必要的;任何能够返回新对象的函数都适合这种模式

语言实现

像构造函数一样,通过执行方法创建一个对象,向该对象添加属性和方法,然后返回

优势

在不创建构造函数的情况下,实现了原型链继承,部分代码缩减会给备份对象增加一些属性缺陷

像构造函数一样,创建寄生方法需要在克隆对象上添加一些所需的属性,这些属性是放置在克隆对象上的私有属性

寄生组合遗传

我们看到上面的组合继承看似完美,但也有缺点(父类实例化两次,子类实例和子类的构造函数属性相同),寄生组合就是为了解决这些问题

代码实现:

函数inheritPrototype({SubType,SuperType }){ const prototype=Object(SuperType . prototype);prototype.constrcutor=SubTypeSubType.prototype=prototype}函数SuperType(name){ this . name=name;this.friends=['a ',' b ']} SuperType . prototype . GetName=function(){ return this . name;} function SupLe(姓名、年龄){ this.age=ageSuperType.call(this,name)} inherit prototype({ SubType,SuperType });SubType . prototype . GetAge=function(){ return this . age } var subtypeShine=new SubType(' Shine ',23);SubTypeShiny . friends . push(' c ')var SubTypeRed=new SubType(' Red ',21);SubTypeRed . friends . push(' d ')console . log(subtypeshiny . getname())//shinyconsole . log(subtypeshiny . getage())//22 console . log(subtypeshiny . friends)/[' a ',' B ',' c'] console.log(子类型red.getname ())//redconsole.log(子类型red.getage ())//21 console.log(子类型red . friends)/[' a ',' B ',' d']基本原则

在子类构造函数中,父类构造函数的这个被调用和应用方法修改,并且父类构造函数被执行,因此子类的实例具有父类构造函数的一些属性。结合子类的原型,修改为父类构造函数的原型,父类原型的构造函数指向子类构造函数

使用场景

实现继承而不使用构造函数,如上所示

继承模式时使用的object()函数不是必需的;任何能够返回新对象的函数都适合这种模式

语言实现

它与组合寄生非常相似,只是修改了子类原型链的继承模式。组合寄生继承父类的原型,而寄生组合寄生通过子类原型继承父类的原型,并将原型的构造函数指向子类构造函数

优势

在少实例化父类一次的情况下,实现了原型链继承和借用构造函数,减少了原型链查找的次数(子类直接继承超类的原型,而不是父类的实例)

下面是组合遗传和寄生组合遗传的原型图比较

以上是边肖介绍的javascript继承的详细讲解和集成,希望对大家有所帮助。如果你有任何问题,请给我留言,边肖会及时回复你。非常感谢您对我们网站的支持!

版权声明:历史上最详细的javascript继承(推荐)是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。

相关文章推荐