继承,一个子类,一个超类,子类想获取超类中的属性和方法,获取之后不满意也可以重写超类中的方法。
新建一个超类:
function fa(){ this.name='father'; } fa.prototype.getname=function(){ return this.name; };
在建一个子类:
function ch(){ this.age=10; } ch.prototype.getage=function(){ return this.age; };怎样让子类获得超类中的属性和方法呢?那就用new实例化一个超类的实例,并把这个实例赋值给子类的原型prototype即可:
ch.prototype=new fa(); //实现了继承这时,子类就不仅拥有自身的属性和方法,还拥有超类的属性和方法,可以实例化一个子类的实例验证一下:
var o=new ch(); //实例化子类 alert(o.getname());//father 调用原本超类中的方法,且能正确运行 alert(o.getage());//10 自己本身的方法以上就是基本的继承方式,无论超类中的属性、方法是定义在函数中的还是在原型中的子类都能继承。下面演示一下继承后再重写:
function fa(){ this.name='father'; } fa.prototype.getname=function(){ return this.name; }; function ch(){ this.age=10; } ch.prototype=new fa(); ch.prototype.getage=function(){ return this.age; }; ch.prototype.getname=function(){ //此处重写了超类中的getname return 'newname'; }; var o=new ch(); alert(o.getname());//newname 此时执行的是重写后的新getname所以返回newname alert(o.getage());
这种继承方式也存在一个问题,那就是对于引用型数据的原型会被实例共享,下面演示一个非引用型和一个引用型:
非引用型实例不共享:
function fa(){ this.name='father'; } fa.prototype.getname=function(){ return this.name; }; function ch(){ this.age=10; } ch.prototype=new fa(); ch.prototype.getage=function(){ return this.age; }; var o=new ch();//两者相互独立 var o2=new ch();//两者相互独立 alert(o.getname()); alert(o2.getname()); o.name='newname';//更改o的name alert(o.name);//o改变 alert(o2.name);//但o2不变,相互不受影响
引用型数据实例会共享:
function fa(){ this.color=['red','green','blue']; //这是个引用型数据 } function ch(){} ch.prototype=new fa(); var o1=new fa(); var o2=new fa(); alert(o1.color); alert(o2.color); o1.color.push('newcolor');//更改o1的属性color alert(o1.color);//red,green,blue,newcolor o1改变 alert(o2.color);//red,green,blue,newcolor o2也跟着改变,因为color是引用型,两者都指向同一个引用型数据color
借用构造函数可解决上述引用型数据的问题:
function sup(){ this.color=['red','green','blue']; } function sub(){ //继承了sup sup.call(this);//关键代码:在子类的构造函数中调用超类的构造函数,从而实现继承 } var o1=new sub(); var o2=new sub(); alert(o1.color);//'red','green','blue' alert(o2.color);//'red','green','blue' o1.color.push('new');//用o1更改color alert(o1.color);//改变'red','green','blue',‘new’ alert(o2.color);//此时不会改变,依然是'red','green','blue'关键代码在注释中已经说明,但借用构造函数的方式依然有个通病:不能函数复用,也就是该共享的不能共享,所以结合两者,通过组合继承的方式更加常用:
function sup(name){ this.name=name; this.color=['red','green','blue']; } sup.prototype.sayname=function(){ alert(this.name); }; function sub(name,age){ //构造函数继承属性(防止实例共享引用型属性) sup.call(this,name); this.age=age; } //原型继承方法,实现方法的共享,实现代码复用 sub.prototype=new sup(); sub.prototype.sayage=function(){ alert(this.age); }; var o=new sub('tom',10); var o2=new sub('cat',20); alert(o.name); alert(o.color); o.sayname(); o.color.push('iii');//修改color属性 alert(o.color);//改变 alert(o2.color);//不变通过上述的代码可看出规律,不需共享的属性借用构造函数实现继承。把需要共享的方法用原型prototype来实现继承。