继承原型链继承实现如下){}//newParent生成的父实例,包含实例属性和原型方法。Child.prototype=newParent();console.log(Child.prototype.constructor);//[Function:Parent]//<1>Child.prototype.constructor=Child;console.log(Child.prototype.constructor);//[Function:Child]constchild=newChild();child.getName();为什么需要<1>?存在的问题是直接覆盖Child的原型对象,通过修改构造函数指向parent来实现指向Child的缺点,如果有一个属性是引用类型,一旦实例修改了该属性,所有实例都会改变。不能传参functionParent(){this.name='Weiyan';this.obj={name:'obj'};}Parent.prototype.getName=function(){console.log(this.name);};functionChild(){}Child.prototype=newParent();Child.prototype.constructor=Child;constchild=newChild();constchild1=newChild();child1.obj.name='child1';//因为他们都在原型对象上寻找相同的东西,所以都会受到影响console.log(child.obj);//{name:'child1'}console.log(child1.obj);//{name:'child1'}创建Child实例时,不允许传参。构造函数继承缺点。属性或方法如果想被继承只能在构造函数中定义。如果方法是在构造函数中定义的。每次创建实例时,都会重新创建方法,这会额外占用一块内存。functionParent(name,obj){this.name=name;这个.obj=obj;this.eat=function(){};}functionChild(id,name,obj){Parent.call(this,name,obj);this.id=id;}constchild=newChild(1,'c1',{name:'薇妍',age:'18'});constchild1=newChild(2,'c2',{name:'微言'});console.log(child.eat===child1.eat);//false导致内存泄漏,内存浪费组合继承结合了构造函数继承和原型链继承。原型链继承:方法有原型,可以随时调用子类。引用类型的属性将在所有实例上共享,并且不能传递参数。构造函数继承:使用call在子构造中重复属性和方法的操作,可以传递参数。functionParent(name,obj,actions){this.name=name;这个.obj=obj;this.actions=actions;}Parent.prototype.eat=function(){console.log(`${this.name}-eat`);};//采用解构的方式,不增删值每次。functionChild(id,...args){//对于实例属性的非共享Parent.apply(this,args);//1this.id=id;}Child.prototype=newParent();//2Child.prototype.constructor=Child;constchild=newChild(1,'c1',{name:'Weiyan',age:'18'},[1]);constchild1=newChild(2,'c2',{name:'Weiyan1'},[2,43]);console.log(child.eat===child1.eat);//truechild.obj.name='asdfasdf';child.actions.pop();console.log(child.obj);//{name:'asdfasdf',age:'18'}console.log(child1.obj);//{name:'Weiyan1'}console.log(child.actions);//[]console.log(child1.actions);//[2,43]缺点父构造函数被调用了两次ParasiticcompositioninheritancefunctionParent(name,obj,actions){this.name=name;这个.obj=obj;this.actions=actions;}Parent.prototype.eat=function(){console.log(`${this.name}-eat`);};//采用解构的方式,不用每次都增减值。functionChild(id,...args){//对于实例属性的非共享Parent.apply(this,args);this.id=id;}//Child.prototype=newParent();//第一个方法。tempconstructor//letTempFunction=function(){};////通过曲线救国,let临时构造函数与父构造函数相同//TempFunction.prototype=Parent.prototype;//这里只继承原型对象,父类中整个构造函数的创建不会执行,(实际上父类中没有执行)//让临时构造函数的实例指向Child.prototype//Child.prototype=newTempFunction();//第二种方法。Object.createChild.prototype=Object.create(Parent.prototype);//为什么不直接这样写呢?修改子类会影响父类//Child.prototype=Parent.prototype;Child.prototype.constructor=孩子;constchild=newChild(1,'c1',{name:'Weiyan',age:'18'},[1]);constchild1=newChild(2,'c2',{name:'Weiyan1'},[2,43]);console.log(child.eat===child1.eat);//truechild.obj.name='newname';child.actions.pop();console.log(child.obj);//{name:'newname',age:'18'}console.log(child1.obj);//{name:'Weiyan1'}console.log(child.actions);//[]console.log(child1.actions);//[2,43]总结本文涉及的知识点,原型,原型链,Object
