由于javascr*pt没有java那么多基本类型,同时也没有提供class这个东西,那么我们想实现javascr*pt的对象创建应该怎么办呢,我简单地从w3c提供的课件中提取了一下几种方法:
一.工厂模式
说白了就是类似于c语言中的定义一个函数,然后给一个struct的各个属性复制,再返回这个struct。代码示例:
fu*ct*o* perso*(*ame,a*e,sex){
var o=*ew Object();
o.*ame=*ame;
o.a*e=a*e;
o.sex=sex;
o.sayName=fu*ct*o*(){
alert(th*s.*ame);
}
retur* o;
}
var perso*1=*ew perso*("wa**ke",21,"Male");
var perso*2=*ew perso*("*aoyua*yua*",34,"Female");
perso*1.sayName();//wa**ke
perso*2.sayName();//*aoyua*yua*
这种办法的确可以创建多个类似的对象,但是个人觉得类似c++中struct与class的区别,它没有解决对象的识别问题。
二.构造函数模式:
其实在javascr*pt中,构造函数和普通函数没什么区别,起码从格式上看来都是一样的,所谓的构造函数无非就是在调用的时候前面加了个*ew,比如上节的var perso*1=*ew perso*(...)。在这种模式中,通过使用th*s,将属性和方法赋值给th*s对象,这样就不用retur*了,同时一般构造函数的首字母会大写的(这也算是个认为加上去的区别吧)。示例代码:
fu*ct*o* *erso*(*ame,a*e,sex){
th*s.*ame=*ame;
th*s.a*e=a*e;
th*s.sex=sex;
th*s.sayName=fu*ct*o*(){...};
}
var perso*1=*ew&*bsp;
var perso*2=*ew&*bsp;
这种模式就可以进行类型检测了,通常用**sta*ceof方法:
alert(perso*1 **sta*ceof Object);//true
alert(perso*1 **sta*ceof *erso*);//true
缺陷:每次实例化一个对象,里面的方法都会被重新创建一遍,浪费资源,所以我们可以想着把它放到全局变量中(但是只被个别方法调用,作用域为全局显得名不副实)。修改如下:
fu*ct*o* *erso*(*ame,a*e,sex){
th*s.*ame=*ame;
th*s.a*e=a*e;
th*s.sex=sex;
th*s.sayName=sayName;
}
fu*ct*o* sayName(){
alert(th*s.*ame);
}
使用这种方法的话,会出现太多的全局函数了,所以我们会在下一种这种方法中解决这个问题。
三.原型模式:
了解什么是prototype(原型):w3c给的概念有点绕,我通俗点说:prototype就是“一个给类的对象添加方法的方法”,
&*bsp;
备注:1.原型的动态性(开头也提到过,对a的拓展)即可以先创建实例再修改原型也可以:
var perso*=*ew *erso*();
*erso*.prototype.saySth(){
alert("* wa*t to sleep");
};
perso*.saySth();//* wa*t to sleep
虽然修改可以立即在所有对象实例中反映过来,但是要重写所有的原型对象就会不一样了。
2.原生对象的原型--不光自定义类型方面原型很重要,所有原生的引用类型都是采用这种模式创建的,所以我们可以自己添加一些方法:
Str***.prototype.startW*th=fu*ct*o*(text){
retur* th*s.**dexof(text)==0;
};
var ms*="Hello,World";
alert(ms*.startW*th("Hello");//true
3.原型模式的缺陷:共享的本性,特别是array。
fu*ct*o* *erso*(){
}
*erso*.prototype={
*ame:"N*cholas",
a*e:29,
job:"Soft E****eer",
fr*e*ds:["wa**ke","yua*yua*"],
sayName:fu*ct*o*(){
alert(th*s.*ame);
}
}
var perso*1=*ew *erso*();
var perso*2=*ew *erso*();
perso*1.fr*e*ds.push("x*j**p***");
alert(perso*1.fr*e*ds);//wa**ke,yua*yua*,x*j**p***
alert(perso*2.fr*e*ds);//wa**ke,yua*yua*,x*j**p***
四.组合
现在只要解决了原型模式中共享造成的缺陷,那么就比较完美了,我们注意到第二条的构造函数模式了吗?下面就是最常见的创建自定义类型的方式:
fu*ct*o* *erso*(*ame,a*e,sex){
th*s.*ame=*ame;
th*s.a*e=a*e;
th*s.sex=sex;
th*s.fr*e*ds=["obama","kobe"];
}
*erso*.prototype={
co*structor:*erso*,
sayName:fu*ct*o*(){}
}
实例属性都是在构造函数中定义,而共享的属性和方法都是在原型模式中定义。
五.其他构造方式:
偶尔会用到,大家可以自己查一下:动态原型模式,寄生构造方式 ,稳妥构造函数模式
以上只是个人的一点总结,欢迎大家阅读并交流!
&*bsp;
&*bsp;