关于javascript中类的继承可以参考阮一峰的Blog《》,说的很透。
一、在javascript中实例化遇到的问题:
下面用《javascript高级程序设计》中的例子来做说明,假如现在定义了一个car的对象,它是Object类的实例。像下面这样的:
复制代码 代码如下:
var oCar=new Object();
oCar.color = "red";
oCar.doors = 4;
oCar.mpg = 23;
oCar.showColor = function () {
alert(this.color);
};
现在又需要这样的一个实例,你可能会像这样来定义:
复制代码 代码如下:
var oCar2 = new Object();
oCar2.color = "blue";
oCar2.doors = 5;
oCar2.mpg = 25;
oCar2.showColor = function () {
alert(this.color);
};
这样遇到的问题是每个对象都需要重新定义一次他的字段和方法。很麻烦。
二、类的定义--工厂方式实现:
对上面的例子进行一个包装,利用函数的返回值来做文章:
复制代码 代码如下:
function createCar() {
var oTempCar = new Object();
oTempCar.color = "red";
oTempCar.doors = 4;
oTempCar.mpg = 23;
oTempCar.showColor = function () {
alert(this.color);
};
return oTempCar;
}
调用方式:
var oCar1 = createCar();
var oCar2 = createCar();
这种方式被称之为工厂方式。工厂方式看起来是省事多了。起码创建一个对象的时候不再需要那么多的行数。因为每个属性(color,doors,mpg)的值都是固定的,还需要再次进行改造,利用参数传递来实现:
复制代码 代码如下:
function createCar(sColor, iDoors, iMpg) {
var oTempCar = new Object();
oTempCar.color = sColor;
oTempCar.doors = iDoors;
oTempCar.mpg = iMpg;
oTempCar.showColor = function () {
alert(this.color);
};
return oTempCar;
}
var oCar1 = createCar("red", 4, 23);
var oCar2 = createCar("red", 4, 23);
oCar1.showColor();
oCar2.showColor();
这样做看似的确可以实现了对象了。实现也很简单,调用也很方便。但是有两个不是很好的地方:
1、从语义上看,在创建对象时没有使用new运算符,似乎不是那么正规(通常创建一个对象都用一个new运算符来实现)。
2、不符合面向对象的特征--封装。在这个例子中,oCar1和oCar2都有自己的showColor方法,并且他们的showColor都是自己的实现。但是事实是他们共享的是同一个函数。
也是有办法解决这个共享函数的问题,利用函数指针来解决。在createCar函数之外再创建一个showColor函数,而oTempCar的showColor方法指向这个showColor函数:
复制代码 代码如下:
function showColor() {
alert(this.color);
}
function createCar(sColor, iDoors, iMpg) {
var oTempCar = new Object();
oTempCar.color = sColor;
oTempCar.doors = iDoors;
oTempCar.mpg = iMpg;
oTempCar.showColor = showColor;
return oTempCar;
}
var oCar1 = createCar("red", 4, 23);
var oCar2 = createCar("red", 4, 23);
oCar1.showColor();
oCar2.showColor();
虽然这样解决了重复创建函数的问题,但这样的话,就使showColor函数看起来不像是对象的方法。
三、类的定义--构造函数方式实现:
复制代码 代码如下:
function Car(sColor, iDoors, iMpg) {
//通过构造函数的形式,会为每个对象生成独立的属性和函数
this.color = sColor;
this.doors = iDoors;
this.mpg = iMpg;
this.showColor = function () {
alert(this.color);
};
}
var oCar1 = new Car("red", 4, 23);
var oCar2 = new Car("red", 4, 23);
oCar1.showColor();
oCar2.showColor();
在Car类中,this指针代表了Car的一个实例,因此不需要返回值。虽然构造函数方式实现了类的定义,但是和工厂方式一样,他也是为每个实例创建一个单独的方法。虽然可以像工厂函数一样在函数之外再创建一个函数利用指针来解决这个问题,但是这么做的话,在语义上没有意义。
四、类的定义--原型方式实现:
利用对象的prototype属性,把它看成是创建新对象所依赖的原型。用空构造函数来设置类名。然后所有的属性和方法都被直接赋予prototype属性。
复制代码 代码如下:
function Car() {
}
Car.prototype.color = "red";
Car.prototype.doors = 4;
Car.prototype.mpg = 23;
Car.prototype.showColor = function () {
alert(this.color);
};
var oCar1 = new Car();
var oCar2 = new Car();
alert(oCar1 instanceof Car);//output true这里存在两个问题:
1、构造函数没有参数。使用原型时,不能通过给函数参数传递参数来初始化属性值。
2、在有多个实例时,对其中一个实例的属性的更改会影响到另外一个实例的属性。
测试代码:
复制代码 代码如下: