js继承原型链构造函数组合继承(原型链+构造函数)原型继承寄生继承寄生组合继承1.原型链继承以父类的实例作为子类的原型//父类函数School(name){//实例属性this.name=name||"父类"this.arr=[1]}//父类原型方法School.prototype={constructor:School,showName(){console.log(this.name);},}//子类函数Student(gender){this.gender=gender}Student.prototype=newSchool("subclass")Student.prototype.constructor=Student//子类的实例letstd1=newStudent()letstd2=newStudent()keyStudent.prototype=newSchool()以父类的实例作为子类的原型newSchool()得到一个实例对象o,它的构造函数是School,o上没有constructor属性,但是会继承School原型上的构造函数给o添加一个属性构造函数指向Student,相当于通过o的继承实现的间接继承,即原型链继承的优势共享方法std1.showName()ontheparentclassprototype//Subclassstd1.showName===std2.showName//true缺点不能给父类传递参数——实例化子类时,不可能想让std1带上名字,你只能手动添加子类instance共享父类构造函数引用属性std1.arr.push(2)console.log(std2.arr);//[1,2]2.构造函数在类的构造函数中执行父类的构造函数子类,并将其更改为functionSchool(name){this.name=name||“父级”this.arr=[1]this.showName=function(){console.log(th是.name);}}functionStudent(name,gender){School.call(this,name)this.gender=gender}letstd1=newStudent("张三")letstd2=newStudent("李四")keySchool.call(this,name)将School中的this改成Student中的this,将name参数传入School并返回,相当于复制父类构造函数中的属性和方法。实例化子类时会出现这种情况复制一次的好处是可以将参数传给父类构造函数——调用std1.arr.push(2)console.log(std2.arr)时不共享父类的引用属性;//[1]缺点方法不能重用std1。showName===std2.showName//false不能继承父类原型上的方法——它只是复制父类构造函数中的属性和方法3.组合继承结合原型链和构造函数学(名称){this.name=名称||“父类”this.arr=[1]}School.prototype={constructor:School,showName(){console.log(this.name);}}函数学生(姓名,性别){学校。call(this,name)this.gender=gender}Student.prototype=newSchool()Student.prototype.constructor=Studentletstd1=newStudent("张三")letstd2=newStudent("李四")包含了1和2的关键语句的优点是可以给父类传递参数共享父类原型上的方法并重用不共享父类构造函数上的引用属性缺点2个关键语句调用父类构造函数两次,生成两个实例Copy,影响性能优化1Student.prototype=newSchool()被Student.prototype=School.proto替换type这个优化解决了两次调用,但是在修改构造函数的时候,父类也会改变优化2(完美)Student.prototype=newSchool()被Student.prototype=Object.create(School.prototype)Object.create代替(proto),创建一个以proto为原型的对象,不调用父类构造函数,得到一个可以继承父类原型的对象Student.prototype.__proto__===School.prototype//真正修改子类的构造函数不会影响父类,类似于1中提到的o对象,只是给它添加一个构造函数letstd1=newStudent("张三")letsch1=newSchool("科学技术")std1.constructor===学生//truesch1.constructor===学校//true4.PrototypeinheritanceDouglasCrockford在2006年提出的一种不涉及严格意义上构造函数的继承方式,也可以通过原型实现对象间的信息共享,无需自定义类型letSchool={name:"ScienceandTechnology",arr:[1],showName(){console.log(this.name);}}functioncreat(o){functionF(){}F.prototype=oreturnnewF()}letsch1=creat(School)sch1.name="Industry"sch1.s??howName()//industrysch1.arr.push(2)letsch2=creat(School)console.log(sch2.arr);//[1,2]sch1.s??howName===sch2.showName//true3中提到的Object.create()的原理与创建功能相同。这种方式的优缺点类似于原型链继承。5.寄生继承letSchool={name:"ScienceandTechnology",arr:[1],showName(){console.log(this.name);}}functioncreate(o){functionF(){}F.prototype=oreturnnewF()}functionenhance(obj){letclone=create(obj)克隆。showAge=function(){console.log(this.age);}returnclone}letsch1=enhance(School)letsch2=enhance(School)sch1.s??howName===sch2.showName;//truesch1.s??howAge===sch2.showAge;//false调用函数创建对象,然后增强新对象,最后返回新对象但是方法不能复用6.寄生组合继承增强的方法和寄生类型不同functionenhance(Student,School){letclone=create(School.prtotype)clone.costructor=StudentStudent.prototye=clone}其实这个方法就是2in3的优化,create相当于Object.create()ES6中class的继承方法这里就不介绍了。后续分析作为类介绍的一部分
