ES实现继承的方式是:实现继承(继承实际的方法)
(1)原型链 (2)借用构造函数 (3)组合继承 (4)原型式继承 (5)寄生式继承 (6)寄生组合式继承
思路:超类有自己的属性和方法,子类也有自己的属性和方法(包含自己独有的属性和方法以及从超类哪里继承来的属性和方法),该方法通过将子类的原型对象作为超类的实例,总之就是使用原型让一个引用类型继承另一个引用类型的属性和方法。 //原型链继承 function SuperType(){ this.superproperty=“superproperty”; this.colors=[“red”,“blue”]; } SuperType.prototype={ getProperty:function(){ alert(this.superproperty); } } function SubType(){ this.subproperty=“subproperty”; } SubType.prototype=new SuperType();//重写原型对象,增加了一个[[prototype]]指针指向了 SuperType.prototype SubType.prototype.getsubProperty=function(){ alert(this.subproperty); } var sub=new SubType(); sub.colors.push(“yellow”); var sub2=new SubType(); alert(sub2.colors); 其中,应该在继承(SubType.prototype=new SuperType();)实现之后,才为子类添加新方法,否则调用在重写子类原型对象之前子类实例特有的方法时,会报TyprError。 通过原型链继承时,搜索机制如下:(1)搜索实例;(2)搜索子类原型;(3)搜索超类原型 但是,通过原型链继承时,不能使用对象字面量创建子类原型的新方法(这是因为利用对象字面量创建原型对象相当于重写了原型对象,这样就会断开之前的继承关系),但可以使用对象字面量创建超类的原型。 而且,利用原型链继承存在的问题就是: (1)通过子类的实例修改超类的属性(引用类型值),这种修改会影响子类的其他实例,也就是像上面的代码中,sub对colors.属性的修改会影响到sub2。
目的:解决原型中包含引用类型值所带来的问题 思路:在子类的执行环境中调用超类,解决原型链继承中引用类型的问题 //借用构造函数继承 function SuperType(){ this.superproperty=“superproperty”; this.colors=[“red”,“blue”]; } function SubType(){ SuperType.call(this); this.subproperty=“subproperty”; }//在子类的执行环境中调用超类
var sub=new SubType(); sub.colors.push(“yellow”); var sub2=new SuperType(); alert(sub2.colors); 通过借用构造函数的方式,就算 sub对colors.属性的修改,也不会影响到sub2。 同时,使用借用构造函数也能实现向超类传递参数 //借用构造函数向超类传递参数 function SuperType(subproperty){ this.superproperty=subproperty; this.colors=[“red”,“blue”]; } function SubType(){ SuperType.call(this,“subproperty”); } var sub=new SubType(); alert(sub.superproperty); 这样,通过在SubType的执行环境中调用超类SuperType,并向超类传递参数,最终子类的实例可以访问到传进来的参数。
思路:原型链实现对原型属性和方法的继承,借用构造函数实现对实例属性的继承。 //组合继承 function SuperType(name){ this.name=name; this.colors=[“red”,“blue”]; } SuperType.prototype={ getname:function(){ alert(this.name); } } function SubType(name,job){ SuperType.call(this,name); this.job=job; } //借用构造函数实现对实例属性的继承 SubType.prototype=new SuperType();//重写原型对象,实现共享信息的继承 SubType.prototype.getjob=function(){ alert(this.job); } var sub=new SubType(“Li”,“student”); sub.getname(); var sub2=new SubType(“Jian”,“student”); sub2.getname(); 这样,就可以使得不同的实例有不同的属性,有相同的方法
思路:先创建一个临时性的构造函数,传入的参数作为构造函数的原型,返回临时性构造函数的新实例,也就是基于已有的对象创建新对象 但是,此类方法中包含引用类型值的属性会被共享的问题仍然存在
组合继承的问题:会调用两次超类的构造函数,一个是在创建子类原型时,一类是在子类中调用超类的构造函数,这样做相当于子类的实例中存在超类的属性;子类的原型中也同样存在超类的属性 解决上述问题,寄生组合式继承—构造函数继承属性,原型链的混合继承方法 //寄生组合式继承 function object(o){ function F(){} F.prototype=o; return new F(); } //原型式继承 function inherit(SubType,SuperType){ var property=object(SuperType.prototype);//创建超类的副本 SubType.property=property; } function SuperType(name){ this.name=name; this.colors=[“red”,“blue”]; } SuperType.prototype={ getname:function(){ alert(this.name); } } function SubType(name,job){ SuperType.call(this,name); this.job=job; } inherit(SubType,SuperType);//重写原型对象,相对于组合继承,该方法少了一次超类构造函数的调用 SubType.prototype.getjob=function(){ alert(this.job); } var sub=new SubType(“Li”,“student”); sub.getname(); var sub2=new SubType(“Jian”,“student”); sub2.getname();