继承,一个子类,一个超类,子类想获取超类中的属性和方法,获取之后不满意也可以重写超类中的方法。
新建一个超类:
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来实现继承。