web前端基础晋级大牛必知的ES5、ES6的7种继承

国内新闻 阅读(1682)

前端必须知道ES5和ES6的七个继承

众所周知,在ES6之前,前端不是类的语法糖,所以你不能像其他语言一样使用extends关键字来获取继承关系,你需要一些额外的方法来实现继承。以下是一些常用方法。红皮书已经全面总结,因此本文基本上是关于红皮书继承章节的一个注释。

原型链继承

函数Parent(){

This.name='arzh'

}

Parent.prototype.getName=function(){

CONSOLE.LOG(this.name)

}

函数Child(){

}

//主要的本质是

Child.prototype=new Parent()

Child.prototype.constructor=Child

Var arzhChild=new Child()

arzhChild.getName()//'arzh'原型链继承缺点:

每个实例对引用类型属性的修改都将由其他实例共享

函数Parent(){

This.names=['arzh','arzh1'];

}

函数Child(){

}

//主要的本质是

Child.prototype=new Parent()

Child.prototype.constructor=Child

Var arzhChild2=new Child()

arzhChild2.names.push( 'arzh2')

Console.log(arzhChild2.names)//['arzh','arzh1','arzh2']

Var arzhChild3=new Child()

arzhChild3.names.push( 'arzh3')

Console.log(arzhChild3.names)//['arzh','arzh1','arzh2','arzh3']

创建Child实例时,不能将参数传递给Parent。这将使Child实例无法自定义其自己的属性(名称)

借用构造函数(经典继承)

函数Parent(){

This.names=['arzh','arzh1']

}

函数Child(){

Parent.call(本)

}

Var arzhChild2=new Child()

arzhChild2.names.push( 'arzh2')

Console.log(arzhChild2.names)//['arzh','arzh1','arzh2']

Var arzhChild3=new Child()

arzhChild3.names.push( 'arzh3')

Console.log(arzhChild3.names)//['arzh','arzh1','arzh3']

优点:

解决了每个实例对引用类型属性的修改将由其他实例共享的问题

子类可以将参数传递给父类

功能父(姓名){

This.name=name

}

功能子(名称){

Parent.call(this,name)

}

Var arzhChild=new Child('arzh');

CONSOLE.LOG(arzhChild.name); //arzh

Var arzhChild1=new Child('arzh1');

CONSOLE.LOG(arzhChild1.name); //arzh1

缺点:

无法重用父类的公共函数

每次子类构造实例必须执行父类函数

组合继承(原型链继承和借用构造函数合并)

功能父(姓名){

This.name=name

This.body=['foot','hand']

}

功能儿童(姓名,年龄){

Parent.call(this,name)

This.age=年龄

}

Child.prototype=new Parent()

Child.prototype.constructor=Child

Var arzhChild1=新孩子('arzh1','18')

arzhChild1.body.push( '头像1')

Console.log(arzhChild1.name,arzhChild1.age)//arzh1 18

Console.log(arzhChild1.body)//['foot','hand','head1']

Var arzhChild2=新孩子('arzh2','20')

arzhChild2.body.push( 'HEAD2')

Console.log(arzhChild2.name,arzhChild2.age)//arzh2 20

Console.log(arzhChild2.body)//['foot','hand','head2']

优点:

解决了每个实例对引用类型属性的修改将由其他实例共享的问题

子类可以将参数传递给父类

可以实现父类方法重用

缺点:

父类构造函数需要执行两次,第一次是Child.prototype=new Parent(),第二次是Parent.call(this,name)导致不必要的浪费

原型继承

将传入对象复制到创建对象的原型以实现继承

函数createObj(o){

函数F(){}

F.prototype=o;

返回新的F();

}

Var person={

名称:'arzh',

身体: ['脚','手']

}

Var person1=createObj(person)

Var person2=createObj(person)

Console.log(person1)//arzh

Person1.body.push( '头')

Console.log(person2)//['foot','hand','head']

缺点:与原型链继承一样,每个实例对引用类型属性的修改都由其他实例共享

寄生遗传

我们可以使用Object.create代替上面的createObj实现,原理基本相同。寄生继承实际上是在createObj内部以某种形式增强对象(增强可以理解为添加对象的方法),最后在增强后返回对象。

函数createEnhanceObj(o){

//而不是createObj的原型继承

Var clone=Object.create(o)

clone.getName=function(){

CONSOLE.LOG( 'arzh')

}

返回克隆;

}

使用createEnhanceObj,您可以在创建对象时以这种方式继承对象方法。

缺点:与构造函数一样,父类函数不能重用,每次创建对象时都会创建一个方法。

寄生结合遗传

您不需要为子类的原型添加父类构造函数。例如,Child.prototype=new Parent()只需要将父类原型的副本复制到子类原型。

函数inheritPrototype(Parent,Child){

Child.prototype=Object.create(Parent.prototype)//创建父类原型的副本并将副本分配给子类原型

Child.prototype.constructor=Child;

}

功能父(姓名){

This.name=name

}

Parent.prototype.getNmae=function(){

CONSOLE.LOG(this.name)

}

功能儿童(颜色){

Parent.call(this,'arzh')

This.color=color

}

inheritPrototype(Parent,Child)

Var arzhChild=new Child('red')

Console.log(arzhChild.name)//'arzh'

优势:没有必要调用父类型的构造函数来指定子类型的原型

ES6继承

ES6支持通过类继承,方法比较简单,代码如下

分数{

构造函数(x,y){

This.x=x

This.y=y

}

的toString(){

返回this.x +''+ this.y

}

}

ColorPoint类扩展了Point {

构造函数(x,y,color){

Super(x,y)//调用父类的构造函数(x,y)

This.color=color

}

的toString(){

返回this.color +''+ super.toString()//调用父类的toString()

}

}

Var colorPoint=new ColorPoint('1','2','red')

Console.log(colorPoint.toString())//red 12

后台回复01面肥带走,记得转发或评论,很好,谢谢你支持95码农民。

0×251e

后台回复01面肥带走,记得转发或评论,很好,谢谢你支持95码农民。

0×251f

http://www.sugys.com/bds7AV5/M2NA