宝哥软件园

JavaScript中继承的三种方式和例子

编辑:宝哥软件园 来源:互联网 时间:2021-10-14

虽然javascript是一种面向对象的语言,但它的继承机制从一开始就不同于其他传统的面向对象语言,它是基于原型继承机制的。然而,在这种机制下,仍然有一些不同的方式来实现继承。

方法1:类继承。

所谓类继承,是指模仿传统面向对象语言的继承模式。继承的和被继承的都是“类”,代码如下:

首先,定义一个父类(或超类):

函数Person(name){ this . name=name;} person . prototype . getname=function(){ return this . name;};

父类person的属性在构造函数中定义,可以保证继承它的子类的name属性不与其共享这个属性,而是单独属于子类。在原型上挂载getName方法的目的是让继承它的子类的多个实例共享这个方法体,这样可以节省内存。(对于多个实例,每次有New实例出来,都会保证这些实例的getName方法引用相同的内存空间,而不是独立的空间。).

定义继承方法扩展,如下所示:

函数extend(subClass,SupClass){ var F=function(){ };f . prototype=SupClass . prototype;subclass . prototype=new F();子类. subClass.prototype.constructor=子类;subclass . SupClass=SupClass . prototype;if(super class . prototype . constructor==object . prototype . constructor){ super class . prototype . constructor=super class;} }

该方法首先创建一个新的F类,其原型就是父类的原型,子类的原型指向F类的一个实例,从而达到继承父类的目的。同时,由于子类的原型被修改,它将修改后的原型的构造函数属性指向子类,使其有一个构造函数,同时,它将一个superClass属性挂载到子类中,子类可以通过这个属性调用父类,从而建立一个子类。

定义一个子类“作者”来继承父类“人”,如下所示:

函数Author(name,books){ Author . superclass . constructor . call(this,name);this.book=书籍;}扩展(作者、人物);author . prototype . getbooks=function(){ return this . book;}这里通过子类的构造函数中其superClass属性调用父类的构造函数,同时采用call方法对该方法调用的this点进行转换,使子类Author也拥有(继承)父类的属性,同时子类有自己的属性书,因此参数书被赋给构造函数中的属性书,达到构造的目的。采用extend函数继承父类Person原型上的属性和方法(其实只继承了方法,因为我们之前只在原型上挂载了方法,属性是在构造函数中定义的)。同时,Author有自己的方法getBooks,挂载在相应的原型上,从而达到在继承的基础上进一步扩展自身的目的。

显然,这种继承方式是采用类似于传统面向对象语言的类继承。它的优点是对于习惯传统面向对象概念的程序员来说很容易,但缺点是过程比较繁琐,内存消耗略大,因为子类也有自己的构造函数和原型,子类和父类的属性是完全隔离的。即使它们具有相同的值,它们也不能共享相同的内存。

方法2:原型继承。

首先,定义一个父类。与其刻意模仿使用构造函数来定义它,不如直接以文字对象的形式定义一个对象,也就是父类。

var Person={ name: '默认名称',getname : function(){ return this . name;} } ;像第一个方法一样,这个对象有一个属性名和一个方法getName。

然后,定义了一个克隆方法来实现子类从父类的继承,如下所示:

函数克隆(obj){ function F()} { F . prototype=obj;返回新的F();}克隆方法创建一个新对象,将对象的原型指向父类,即参数obj,同时返回对象。

最后,子类通过克隆函数继承父类,如下所示:

var作者=克隆(人);author . book=[' JavaScript '];author . show book=function(){ return this . book;}这里定义了一个子类,通过克隆函数继承父类Person,同时扩展了一个属性书和一个方法showBook。这里,子类也有属性名,但是它的值与父类的值相同,所以不会被覆盖。如果不同,可以使用。

Author.name=' new name重写该属性以获取子类的新名称属性值。

与类继承相比,这种原型继承更简单、更自然。同时,如果子类的属性和父类的属性值相同,不能修改,那么它们实际上共享相同的内存空间,比如上面的name属性。缺点是程序员很难习惯传统的面向对象。如果他们想在两者之间选择,这种方式无疑更好。

既然javascript采用基于原型的继承,每个对象的原型只能指向一个特定类的一个实例(而不能指向多个实例),那么如何实现多重继承(即让一个类同时拥有多个类的方法和属性,而不自己定义这些方法和属性)?

在javascript设计模式中,给出了一种混合元素类的方法:

首先,定义一个掺杂类来存储一些常用的方法和属性,可以通过扩展的方式添加到任何其他类中,这样添加的类就有了这个类的一些方法和属性。如果同时定义多个掺杂类并添加到一个类中,那么这个类将间接实现“多重继承”。基于这一思想,实现如下:

掺杂剂类别的定义:

var Mixin=function(){ };mixin . prototype={ serialize 3360 function(){ var output=[];for(键在此){ output.push(键' : ' this[key]);}返回output.join(',');}}掺杂类有一个serialize方法,用于遍历自身,输出自己的属性和属性值,并以逗号分隔的字符串形式返回。

定义一个扩展方法,用于使一个类在扩展后拥有掺杂类的属性或方法,如下:

函数扩充(receivingClass,giving class){ if(arguments[2]){ for(var I=2,len=arguments.length伊琳;I){ receiving class . prototype[arguments[I]]=giving class . prototype[arguments[I]];} } else { for(givingclass . prototype中的methodName in(!receiving class . prototype[method name]){ receiving class . prototype[method name]=giving class . prototype[method name];}}}}这个方法默认有两个参数,第一个参数是接受扩展类,第二个参数是掺杂类(用来扩展其他类的类),可能还有其他参数。如果大于两个参数,则以下参数为方法或属性名,表示扩展类只希望继承掺杂类的指定属性或方法,否则默认继承掺杂类的所有属性和方法。在此功能中,第一个中频分数。这种方法的本质是将掺杂类的原型的属性和方法扩展(添加)到扩展类的原型中,使其具有掺杂类的属性和方法。

最后,利用扩展方法实现多重继承。

扩充(作者,米欣);var author=new Author('js ',['javascript设计模式']);alert(author . serialize());这里定义了一个作者类,继承了Person的父类,具有Mixin的方法和属性。如果你愿意,可以定义n个掺杂类来扩展这个类,这样也可以继承你定义的其他掺杂类的属性和方法,从而实现多重继承。最后,作者序列化方法的运行结果如下:

你会发现这个类同时具有person类、Author类和Mixin类的属性和方法,其中Person和Mixin的属性和方法是通过“继承”得到的,实际上实现了多重继承。

更多资讯
游戏推荐
更多+