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

JavaScript的几种继承方法

时间:2023-03-28 00:23:40 HTML

这篇文章叫笔记更贴切,内容来自《JavaScript高级程序设计 (第三版)》第6.3章JavaScript继承的几种继承方法原型链继承使用构造函数继承(经典继承)组合继承:原型链+借用构造函数(最常用)原型继承(Object.create)寄生继承寄生组合继承(理想)ES6中的继承1.原型链继承子类型的原型是父类型的实例对象functionParent(){this.name='大明星';this.colors=['red','blue','yellow'];}Parent.prototype.getName=function(){console.log(this.name)}functionChild(){this.subName='litterStar';}//核心代码:子类型的原型是父类型的实例对象Child.prototype=newParent();letchild1=newChild();letchild2=newChild();child1.getName();//bigStarchild1.colors.push('pink');//修改child1.colors会影响child2.colorsconsole.log(child1.colors);//['红色','蓝色','黄色','粉色']console.log(child2.colors);//['red','blue','yellow','pink']注意核心代码:Child.prototype=newParent();特点:父类在构造函数上新增一个方法,子类可以访问。缺点:原型对象的所有属性都是所有实例共享的,child1修改颜色会影响child2的颜色。创建子类实例时,无法向父类的构造函数传递参数2.借助构造函数继承(经典继承),在子类的构造函数中使用call()或apply()调用父类构造函数functionParent(name){this.name=name;this.colors=['red','blue','yellow'];}Parent.prototype.getName=function(){console.log(this.name)}functionChild(name,age){//核心代码:“第二个”父类型构造函数Parent.call(this,name);this.age=age;}letchild1=newChild('litterStar');letchild2=newChild('luckyStar');console.log(child1.name);//litterStarconsole.log(child2.name);//luckyStar//该方法只实现了部分继承。如果父类的原型还有方法和属性,子类就无法得到这些方法和属性child1.getName();//TypeError:child1.getNameisnotafunction注意核心代码:Parent.call(this,name);特点:避免引用类型的属性被所有实例共享。创建子类实例时,可以调用父类传参的缺点实例不是父类的实例,但是子类的实例只能继承父类的实例属性和方法,不能继承原型属性和方法。无法实现功能复用。每创建一个实例,都会重新创建方法,影响性能3.组合继承:原型链+借用构造函数(最常用)functionParent(name){this.name=name;this.colors=['red','blue','yellow'];}Parent.prototype.getName=function(){console.log(this.name)}functionChild(name,age){//核心代码①Parent.call(这个,名字);this.age=age;}//核心代码②:子类型的原型是父类型的实例对象Child.prototype=newParent();Child.prototype.constructor=Child;//可以给通过子类构造父类的构造函数letchild1=newChild('litterStar');letchild2=newChild('luckyStar');child1.getName();//litterStarchild2.getName();//luckyStarchild1.colors.push('pink');//修改child1.colors不会影响child2.colorsconsole.log(child1.colors);//['红色','蓝色','黄色','粉色']console.log(child2.colors);//['red','blue','yellow']注意核心代码:Parent.call(this,name);和Child.prototype=新父母();特性结合了原型链继承和借用构造函数的优点,号称是JavaScript中最常用的继承模式缺点调用父类构造函数两次,生成两个实例,一次是设置子类型实例的原型Child.prototype=newParent();一旦创建子类型实例letchild1=newChild('litterStar');,调用new就会执行Parent.call(this,name);这时候会再次调用One-timeParentconstructor4.Prototypeinheritance(Object.create)借助原型,可以根据已有的方法创建对象。varB=Object.create(A)以A对象为原型生成A对象,B继承了A的所有属性和方法。constperson={name:'star',colors:['red','blue'],}//核心代码:Object.createconstperson1=Object.create(person);constperson2=Object.create(person);person1.name='litterstar';person2.name='luckystar';person1.colors.push('yellow');console.log(person1.colors);//['红色','蓝色','黄色']console.log(person2.colors);//['red','blue','yellow']注意核心代码:constperson1=Object.create(person);该特性没有严格的构造函数,借助原型可以在现有对象的基础上创建新对象。缺点原型对象的所有属性都由所有实例共享。person1修改颜色会影响person2的颜色,这和原型链继承是一样的。5.寄生继承创建一个函数来封装继承过程,在内部以某种方式增强对象functioncreateObj(original){//通过调用函数创建一个新对象varclone=Object.create(original);//以某种方式增强此对象clone.sayName=function(){console.log('hi');}//returnthisobjectreturnclone;}缺点:每次创建对象,都会重新创建方法,与6.寄生组合继承(理想)我们可以先回忆一下JavaScript中最常用的继承模式:组合继承(原型链+借用的构造函数),它最大的缺点是会调用父结构两次函数(Child.prototype=newParent();andletchild1=newChild('litterStar');)。能不能想办法调用一次?允许Child.prototype访问Parent.prototype。我们不能直接使用Child.prototype=Parent.prototype,因为会有一些副作用,你可能在修改Child.prototype的同时修改Parent.prototype。Object.create(...)可以用来实现Object.createMDN上的解释:它会创建一个新的对象,使用已有的对象提供新创建对象的__proto__函数Parent(name){this.name=姓名;this.colors=['red','blue','yellow'];}Parent.prototype.getName=function(){console.log(this.name)}functionChild(name,age){//核心代码①Parent.call(this,name);this.age=age;}//核心代码②Child.prototype=Object.create(Parent.prototype);Child.prototype.constructor=孩子;注意核心代码:Parent。打电话(这个,名字);和Child.prototype=Object.create(Parent.prototype);寄生组合继承,结合了寄生继承和组合继承的优点,是引用类型最理想的继承范式。7、ES6中类的继承ES6中引入了class关键字,可以通过extends关键字实现继承。classParent{}classChildextendsParent{constructor(name,age,color){//调用父类的constructor(name,age)super(name,age);this.color=颜色;}toString(){returnthis.color+''+super.toString();//调用父类的toString()}}class关键字只是原型的语法糖,JavaScript继承仍然是基于原型实现的。参考JavaScript的六种常见继承方式JS继承的几种方式JavaScript深入继承的各种方式及优缺点ECMAScript6类继承简介