目录 (Table of Contents)
[TOCM]
工厂方式
通过创建能返回特定类型的对象的工厂函数,来创建类。
方法1:
function CreateCar(sColor, iDoors, iMpg) {
var oTempCar = new Object;
oTempCar.color = sColor;
oTempCar.door = iDoor;
oTempCar.mpg = iMpg;
oTempCar.showColor = functiong() {
alert(this.color)
}
return oTempCar;
}
var oCar1 = CreateCar("red", 4, 23);
var oCar2 = CreateCar("blue", 3, 25);
oCar1.showColor(); //outputs "red"
oCar2.showColor(); //outputs "blue"
上诉方式有个问题,就是在调用CreateCar创建对象时,会为每个对象都创建一个showColor()方法,意味着每个对象都有自己的showColor()版本,实际上每个对象都共享了一个,为了解决以上问题,有些开发者在工厂为定义方法,如下。
方法2:
function showColor() {
alter(this.color);
}
function CreateCar(sColor, iDoors, iMpg) {
var oTempCar = new Object;
oTempCar.color = sColor;
oTempCar.door = iDoor;
oTempCar.mpg = iMpg;
oTempCar.showColor = showColor();
return oTempCar;
}
var oCar1 = CreateCar("red", 4, 23);
var oCar2 = CreateCar("blue", 3, 25);
oCar1.showColor(); //outputs "red"
oCar2.showColor(); //outputs "blue"
从功能上讲,解决了重复创建函数对象的问题,但是该函数看起来不像对象的方法。
构造函数方式
方法:
function Car(sColor, iDoor, iMpg) {
this.color = sColor;
this.door = iDoor;
this.mpg = iMpg;
this.showColor = function() {
alert(this.color);
}
}
var oCar1 = new Car("red", 4, 23);
var oCar2 = new Car("blue", 3, 25);
需要注意的是,类名按惯例首字母大写。
构造函数方式和工厂方式很相似,同样会重复生成函数,虽然可以在类外定义方法,但是任然没有解决问题。
原型方式
方法:
function Car() {
}
Car.prototype.color = "red";
Car.prototype.doors = 4;
Car.prototype.mpg = 23;
Car.prototype.drivers = new Array("Mike", "Sue");
Car.prototype.showColor = function () {
alert(this.color);
}
var oCar1 = new Car();
var oCar2 = new Car();
oCar1.drivers.push("Matt");
alter(oCar1.drivers); //outputs "Mike,Sue,Matt"
alter(oCar2.drivers); //outputs "Mike,Sue,Matt"
这段代码中,通过给Car的prototype属性添加属性去定义Car对象的属性。在创建对象是,所有实例存放的都是指向showColor函数的指针。除了函数外,属性也是保存的指针。
因为是保存指针的缘故,所以任意一个实例改变自己属性的值,就会引起其他实例属性值发生变化。而这个是不愿意被看到的。
混合的构造函数/原型方式(最常用)
方法:
function Car(sColor, iDoor, iMpg) {
this.color = sColor;
this.door = iDoor;
this.mpg = iMpg;
this.drivers = new Array("Mike", "Sue");
}
Car.prototype.showColor = function () {
alert(this.color);
}
var oCar1 = new Car("red", 4, 23);
var oCar2 = new Car("blue", 3, 25);
oCar1.drivers.push("Matt");
alter(oCar1.drivers); //outputs "Mike,Sue,Matt"
alter(oCar2.drivers); //outputs "Mike,Sue"
这种方法是ECMAScript采用的主要方式,它具有其他方式的特性,却没有他们的副作用。不过有些开发者仍认为这种方法不够完美。
动态原型方法(合理可用)
方法:
function Car(sColor, iDoor, iMpg) {
this.color = sColor;
this.door = iDoor;
this.mpg = iMpg;
this.drivers = new Array("Mike", "Sue");
if(typeof Car._initialized == "undefined") {
Car.prototype.showColor = function () {
alert(this.color);
};
Car._initialized = true;
}
}
通过判断Car._initialized,进行函数定义,保证该方法只会赋值一次。所以只有在第一次实例化的时候,才会创建函数showColor 。
混合工厂方式
方法:
function Car() {
var oTempCar = new Object;
oTempCar.color = "red";
oTempCar.doors = 4;
oTempCar.mpg = 23;
oTempCar.showColor = function () {
alert(this.color);
};
return oTempCar;
}
var car = new Car();
这种方式的目的是创建假的构造函数,只返回另一种对象的新实例。
这种方式在内部管理方面与经典方式有着相同的问题。除非万不得已避免使用。