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

ES5和ES6如何实现继承

时间:2023-03-27 10:53:26 JavaScript

完整高频题库仓库地址:https://github.com/hzfe/aweso...完整高频题库阅读地址:https://febook.hzfe.org/ES5、ES6继承问题相关问题原型链概念解答要点原型链继承构造函数继承ES6类继承继承是指子类型具有父类型的属性和行为,实现代码复用和设计分离。JavaScript中的继承主要是通过原型链和构造函数来实现的。常见的继承方式有:ES6中的类继承、原型链继承、寄生组合继承等。深入知识点1.原型链原型链的本质是扩展了原型搜索机制。每个实例对象都有一个私有属性\_\_proto\_\_。该属性指向其构造函数的原型对象prototype。这个原型对象的\_\_proto\_\_也可以指向其他构造函数的原型。一层一层,直到一个对象的\_\_proto\_\_指向null。根据定义,null没有原型,充当此原型链中的最后一环。当试图访问一个对象的属性时,它不仅在对象上搜索,而且在对象的原型上搜索,以及对象原型的原型原型,等等,直到找到具有匹配名称的属性或直到这个链接列表结束(Object.prototype.__proto__===null)。2.原型链继承原型链继承的思想:一个引用类型继承另一个引用类型的属性和方法。functionSuperType(){this.b=[1,2,3];}functionSubType(){}SubType.prototype=newSuperType();SubType.prototype.constructor=SubType;varsub1=newSubType();varsub2=newSubType();//这里对引用类型数据进行操作sub1.b.push(4);console.log(sub1.b);//[1,2,3,4]console.log(sub2.b);//[1,2,3,4]console.log(sub1instanceofSuperType);//true优点:父类增加了新的原型方法/原型属性,可以被子类访问。简单易行。缺点:无法实现多重继承。由于原型中的引用值是共享的,因此实例上的更改将直接影响原型。创建子类实例时,不能向父类构造函数传递参数。3.构造函数继承构造函数继承的思想:在子类构造函数中调用父类的构造函数,这样所有需要继承的属性都定义在实例对象上。functionSuperType(name){this.name=name;this.b=[1,2,3];}SuperType.prototype.say=function(){console.log("HZFE");};functionSubType(name){SuperType.call(this,name);}varsub1=newSubType();varsub2=newSubType();//传递参数varsub3=newSubType("Hzfe");sub1.say();//使用构造函数继承不访问原型链,并且say方法不能调用console.log(sub3.name);//Hzfesub1.b.push(4);//解决原型链继承中子类实例共享父类的问题引用属性问题console.log(sub1.b);//[1,2,3,4]console.log(sub2.b);//[1,2,3]console.log(sub1instanceofSuperType);//false优点:解决子类实例在原型链继承中共享父类引用属性的问题。您可以在子类型构造函数中将参数传递给超类构造函数。可以实现多重继承(调用多个父类对象)。缺点:实例不是父类的实例,而是子类的实例。只能继承父类的实例属性和方法,不能继承原型属性和方法。无法实现函数复用,每个子类都有一份父类的实例函数,影响性能。4.组合继承(伪经典继承)组合继承的思想:使用原型链实现原型属性和方法的继承,使用构造函数实现实例属性的继承。functionSuperType(name){this.name=name;this.a="HZFE";this.b=[1,2,3,4];}SuperType.prototype.say=function(){console.log("HZFE");};functionSubType(name){SuperType.call(this,name);//第二次调用SuperType}SubType.prototype=newSuperType();//首先调用SuperTypeSubType.prototype.constructor=SubType;优点:可以继承实例属性/方法和原型属性/方法。不存在引用属性共享问题。可以传参的函数可以复用缺点:父类构造函数被调用了两次(耗内存),生成了两个实例。5.寄生组合继承寄生组合继承的思路:借用构造函数继承属性,采用混合原型链继承方式。//在函数内部,第一步是创建父类原型的副本,第二步是将构造函数属性添加到创建的副本中,//从而弥补因重写而丢失的默认构造函数属性。在最后一步中,新创建的对象(即副本)被分配给类型的原型。functioninheritPrototype(subType,superType){varprototype=Object.create(superType.prototype);//创建对象prototype.constructor=subType;//增强对象subType.prototype=prototype;//指定对象}functionSuperType(name){this.name=name;}SuperType.prototype.sayName=function(){console.log(this.name);};functionSubType(name,num){SuperType.call(这个,名字);this.num=num;}inheritPrototype(SubType,SuperType);SubType.prototype.sayNum=function(){console.log(this.num);};优点:只调用一次SuperType构造函数,避免创建子类型SubType.prototype必需的属性。可以正常使用instanceof和isPrototypeOf()。缺点:实现比较复杂6、ES6中类的继承ES6中引入了class关键字,可以通过extends关键字继承类,也可以通过static关键字定义类的静态方法,即通过修改原型链,比ES5继承更清晰、更方便。需要注意的是,class关键字只是原型的语法糖,JavaScript的继承仍然是基于原型来实现的。classPet{constructor(name,age){this.name=name;这个。年龄=年龄;}showName(){console.log("调用父类方法");console.log(this.name,this.age);}}//定义一个子类classDogextendsPet{constructor(name,age,color){super(name,age);//通过super调用父类的构造函数this.color=color;}showName(){console.log("子类的调用方法");console.log(this.name,this.age,this.color);}}优点:清晰方便缺点:不是所有的浏览器都支持类。参考资料JS中实现继承的几种方式阮一峰ES6类继承介绍《JavaScript 高级程序设计》《你不知道的 JavaScript》