要明白javascript中的继承,就要明白javascript中的构造函数及原型的概念(如果不懂原型,请参考我的文档《javascript中的原型》
http://han2000lei.iteye.com/admin/blogs/324686)。
javascript中的构造函数与java的不同:
1.java的构造方法是显式的写在类中,如果不写,则默认有一个无参的构造方法。java在继承时,是类层次上的继承,即一个类继承另一个类。
2.javascript的继承是基于原型的继承。javascript的构造方法就是我们自己定义的一个函数(所有的函数都有一个内置的原型对象,是我们看不见的,但我们可以访问:函数名.prototype ----这就是函数中的原型对象 ),这个函数即是类,又是构造方法。例如:我们有一个代表矩形的构造函数,其定义如下:
function Rectangle(w,h){
this.width = w; //代表矩形的宽
this.height= h; //代表矩形的高
}
Rectangle.prototype.area=function(){//此定义是构造函数原型对象的一个属性,它代表面积
return this.width * this.height;
}
现在,我们要定义一个子类的构造函数(javascript中是通过在构造函数中的定义来实现的继承),来继承这个父类:
1,首先,调用父类的构造函数,以便它能够初始化width和height。我们使用call()方法(如果不知道此方法的作用,请参考我的文档《javascript中的call()与apply()方法》
http://han2000lei.iteye.com/admin/blogs/324680),来援引构造方法使对象初始化。在子类的构造中调用父类的构造,这就是所谓的构造函数链。
function PositionedRectangle(x,y,w,h){
Rectangle.call(this,w,h); //使用函数的call()方法,以便初始化父类构造函数中的属性
this.x = x;
this.y = y;
}
2,当我们定义了这个PositionedRectangle()构造函数来用它创建一个对象时,它会使用默认的原型对象来创建对象,而没有使用父类的原型对象。这样我们得到的子类对象还没有继承父类。我们必须明确地创造我们的原型对象,使子类构造函数中的原型对象成为父类的一个实例。
PositionedRectangle.prototype = new Rectangle();
3.我们建立这个原型对象只是想继承父类中的原型对象,一般情况下并不想继承父类的width和height属性,所以删除它们的原型(注:如果想保留,你也可以不删)。
delete PositionedRectangle.prototype.width;
delete PositionedRectangle.prototype.height;
4,由于父类的构造方法Rectangle()的原型对象的属性constructor,指向父类的构造函数本身。PositionedRectangle构造函数的原型中的constructor现在还是指向的父类的构造,我们必须重新分配此默认构造属性constructor,使用它指向子类的构造函数。
PositionedRectangle.prototype.constructor = PositionedRectangle;
5,好了,现在我们已经配置好了。现在PositionedRectangle已经成为Rectangle的子类了。
可以看出,javascript的继承要比java的继承麻烦的多。不过惯成自然,当熟悉了就不觉的麻烦了,其继承也就这么几步。下面将子类PositionedRectangle的代码综合起来,以方便查看
function PositionedRectangle(x,y,w,h){
Rectangle.call(this,w,h); //使用函数的call()方法,以便初始化父类构造函数中的属性
this.x = x;
this.y = y;
}
PositionedRectangle.prototype = new Rectangle();
delete PositionedRectangle.prototype.width;
delete PositionedRectangle.prototype.height;
PositionedRectangle.prototype.constructor = PositionedRectangle;