浅谈javascript的面向对象(一)如何实现类
2008-10-25 10:11
543 查看
这里将讨论关于javascript的面向对象特点的实现,如封装,组合,继承,多态。
1.对象的声明与实例化。
var oObject=new Object();//如果构造函数中没有参数,则Object后的括号可有可无。
2.对象的销毁。
javascript中有无用存储单元收集程序,也就说不必专门设计函数来销毁对象。当对象没有被再引用时,对象使用的内存将被回收。一般把对象强制为null,可以强制释放。
3. 关于早绑定与晚绑定:
early binding:是在实例化对象之前定义它的属性与方法。这样编译器或解释程序就能提前转换机器代码。而javascript不是 强类型语言,所以不支持。
late binding: 是在编译器或解释程序运行前,不知对象的类型,使用late binding无需检查对象的类型,只要检查对象是否支持对应的属性或方法即可。javascript所有变量都采用此方法。
4.关于内置对象,只有两个Global ,Math。而Array,Function等都是本地对象。关于数据处理,下次专门讨论。
Global 其实它是不存在,如果你写 var pointer=Global 则将产生错误。这是由于在javascript中所有方法都必须是某种对象的方法。比如它有的方法:isNaN(),isFinite(),parseInt()等。
5.类的创建。
1) 原始法 .对象的属性可心服在对象创建后动态定义。所以有下面的方式:
var oCar=new Object();
oCar.color="red"; //属性
oCar.doors=4;
oCar.showColor=function()//方法
{
alert(this.color); //关键字this 用来引用对象的属性。如果改成 color将出错
}
这里意思是创建对象oCar,并给它赋予了几个属性与方法。下面就可以测试一下oCar的使用了。如oCar.showColor();//将输出 red.
这种方式的缺点:如果要创建多个对象,我想你将很头疼,因为这样只是实现一个对象的创建。很自然的我们会想到用函数把上面的方式封装起来。
2) 工厂方式。了解设计模式的都应该知道有个工厂模式,这里的意思差不多,就是批量生产对象。
改造上面的实现方式。
function createCar()
{
var oTempCar=new Object;
oTempCar.color="red";
oTempCar.doors=4;
oTempCar.showColor=function(){alert(this.color);}
return oTempCar; //这里很关键
}
这样我们就实现了多个对象创建。var oCar1=createCar(); var oCar2=createCar();上面是用函数的方式实现,是函数都能有参数,所以还可以为对象传递参数,而不是使用默认。如下:
function createCar(sColor,iDoors)
{
var oTempCar=new Object;
oTempCar.color=sColor;
oTempCar.doors=iDoors;
oTempCar.showColor=function(){alert(this.color);}
return oTempCar; //这里很关键
}
缺点:没用用new关键字来创建对象,不符合面向对象创建对象的编程习惯。还有创建一个对象就创建一个函数showColor。在资源上很浪费。也让不同的对象有了不同的showColor。可能你已经想到把函数的实现放到外面去。看一下实现:
function showColor()
{
alert(this.color);
}
function createCar(sColor,iDoors)
{
var oTempCar=new Object;
oTempCar.color=sColor;
oTempCar.doors=iDoors;
oTempCar.showColor=showColor;
return oTempCar; //这里很关键
}
这样就避免了同一函数多次创建的问题,不过还是没有像C#那样的 string str=new string();这样的东东爽吧。
3)构造函数法
function Car(sColor,iDoors)
{
this.color =sColor;
this.doors=iDoors;
this.showColor=new function(){ alert(this.color);}
}
var oCar1=new Car("red",2);
oCar1.showColor();//输出 red
这时里面没有临时对象oTempCar了吧。全用this引用。而默认情况返回的就是this。你可能会问这不又是多次创建函数了吗,没错。请看下一种方法。
4) 原形方法.此方法利用了对象的prototype属性。对上面进行如下改造:
function Car(){}
Car.prototype.color="red"; //prototype指定新对象的依赖的原型。
Car.prototype.doors=4;
Car.prototype.showColor=function(){alert(this.color);}
//test;
var oCar=new Car();
这样所有属性不会因创建多个对象而有不同的版本。此外运用此种方法,还可以用instanceof 来检查对象的类型。如: alert( oCar instanceof Car) ;//outputs "true".
遗憾的是,这个构造函数中没有参数,只能使用默认参数值,这就意味着要等对象创建后才能修改其属性的值。如果你是个聪明的人你可能已经发现,这次把函数独立出来了,可是属性也分了出来,这样不同对象的属性开始共享属性,也就是说。如果有下面的情况,我们为Car加上一个引用类型。
function Car(){}
Car.prototype.color="red"; //prototype指定新对象的依赖的原型。
Car.prototype.doors=4;
Car.prototype.drivers=new Array("china","中国");
Car.prototype.showColor=function(){alert(this.color);}
//test;
var oCar1=new Car();
var oCar2=new Car();
oCar1.push("操死小日本");
alert(oCar1.drivers);//output "china,中国,操死小日本"
alert(oCar2.drivers);//output "china,中国,操死小日本"
由于drivers是引用值,所以Car的两个实例都指向一个值。
这与真正的面向对象还是一段距离。再次进行改造。
5) 混合的构造/原形方式。
可能你已经想到,既然用prototype属性能让对象属性外置,那何不把对象的属性放在构造函数内,而把方法用prototype引用到构造函数外内。这样就可以解决所有问题了:
function Car(sColor,iDoors)
{
this.colors=sColor;
this.doors=iDoors;
this.drivers=new Array("东京大屠杀吧!");
}
Car.prototype.showColor=function()
{alert(this.color);}
var oCar1=new Car("red",4);
var oCar2=new Car("blue",4);
oCar1.drivers.push("给东京来个原子炸");
alert(oCar1.drivers)//output "东京大屠杀吧,给东京来个原子炸";
alert(oCar2.drivers)//output "给东京来个原子炸".
由于使用了原型方法,所以仍可以用instanceof来检查对象的类型,详情见上。只要是用了原型的方式实现类则可用instanceof来检查对象,而什么是原型,用了prototype的就是了。
好了到现已经差不多了吧,没有了多个函数版本造成的内存浪费问题,没有属性共享问题。和面向对象已经很接近了。但是美中不足的是函数必须要写到类之外,如果知道C++的应该知道,它可以把方法内置,也可以写在类内。写在外面让人阅读起来很费劲。所以继续改造。
6)动态原型法。它与混合的构造/原型差不多,只是函数的实现位置转到类内部。
function Car(sColor,iDoors)
{
this.colors=sColor;
this.doors=iDoors;
this.drivers=new Array("东京大屠杀吧!");
//注意这里
if(typeof Car._initialized=="true")
{
Car.prototype.showColor=function()
{alert(this.color);}
Car._initialized=true;//以_开头的属性被大家公的一种私有属性的表示方法,但是只是表示上的私有,而它是public的。
}
}
OK。到现在为止,用javascript实现类,有几种方式已经介绍完了。欢迎交流。
1.对象的声明与实例化。
var oObject=new Object();//如果构造函数中没有参数,则Object后的括号可有可无。
2.对象的销毁。
javascript中有无用存储单元收集程序,也就说不必专门设计函数来销毁对象。当对象没有被再引用时,对象使用的内存将被回收。一般把对象强制为null,可以强制释放。
3. 关于早绑定与晚绑定:
early binding:是在实例化对象之前定义它的属性与方法。这样编译器或解释程序就能提前转换机器代码。而javascript不是 强类型语言,所以不支持。
late binding: 是在编译器或解释程序运行前,不知对象的类型,使用late binding无需检查对象的类型,只要检查对象是否支持对应的属性或方法即可。javascript所有变量都采用此方法。
4.关于内置对象,只有两个Global ,Math。而Array,Function等都是本地对象。关于数据处理,下次专门讨论。
Global 其实它是不存在,如果你写 var pointer=Global 则将产生错误。这是由于在javascript中所有方法都必须是某种对象的方法。比如它有的方法:isNaN(),isFinite(),parseInt()等。
5.类的创建。
1) 原始法 .对象的属性可心服在对象创建后动态定义。所以有下面的方式:
var oCar=new Object();
oCar.color="red"; //属性
oCar.doors=4;
oCar.showColor=function()//方法
{
alert(this.color); //关键字this 用来引用对象的属性。如果改成 color将出错
}
这里意思是创建对象oCar,并给它赋予了几个属性与方法。下面就可以测试一下oCar的使用了。如oCar.showColor();//将输出 red.
这种方式的缺点:如果要创建多个对象,我想你将很头疼,因为这样只是实现一个对象的创建。很自然的我们会想到用函数把上面的方式封装起来。
2) 工厂方式。了解设计模式的都应该知道有个工厂模式,这里的意思差不多,就是批量生产对象。
改造上面的实现方式。
function createCar()
{
var oTempCar=new Object;
oTempCar.color="red";
oTempCar.doors=4;
oTempCar.showColor=function(){alert(this.color);}
return oTempCar; //这里很关键
}
这样我们就实现了多个对象创建。var oCar1=createCar(); var oCar2=createCar();上面是用函数的方式实现,是函数都能有参数,所以还可以为对象传递参数,而不是使用默认。如下:
function createCar(sColor,iDoors)
{
var oTempCar=new Object;
oTempCar.color=sColor;
oTempCar.doors=iDoors;
oTempCar.showColor=function(){alert(this.color);}
return oTempCar; //这里很关键
}
缺点:没用用new关键字来创建对象,不符合面向对象创建对象的编程习惯。还有创建一个对象就创建一个函数showColor。在资源上很浪费。也让不同的对象有了不同的showColor。可能你已经想到把函数的实现放到外面去。看一下实现:
function showColor()
{
alert(this.color);
}
function createCar(sColor,iDoors)
{
var oTempCar=new Object;
oTempCar.color=sColor;
oTempCar.doors=iDoors;
oTempCar.showColor=showColor;
return oTempCar; //这里很关键
}
这样就避免了同一函数多次创建的问题,不过还是没有像C#那样的 string str=new string();这样的东东爽吧。
3)构造函数法
function Car(sColor,iDoors)
{
this.color =sColor;
this.doors=iDoors;
this.showColor=new function(){ alert(this.color);}
}
var oCar1=new Car("red",2);
oCar1.showColor();//输出 red
这时里面没有临时对象oTempCar了吧。全用this引用。而默认情况返回的就是this。你可能会问这不又是多次创建函数了吗,没错。请看下一种方法。
4) 原形方法.此方法利用了对象的prototype属性。对上面进行如下改造:
function Car(){}
Car.prototype.color="red"; //prototype指定新对象的依赖的原型。
Car.prototype.doors=4;
Car.prototype.showColor=function(){alert(this.color);}
//test;
var oCar=new Car();
这样所有属性不会因创建多个对象而有不同的版本。此外运用此种方法,还可以用instanceof 来检查对象的类型。如: alert( oCar instanceof Car) ;//outputs "true".
遗憾的是,这个构造函数中没有参数,只能使用默认参数值,这就意味着要等对象创建后才能修改其属性的值。如果你是个聪明的人你可能已经发现,这次把函数独立出来了,可是属性也分了出来,这样不同对象的属性开始共享属性,也就是说。如果有下面的情况,我们为Car加上一个引用类型。
function Car(){}
Car.prototype.color="red"; //prototype指定新对象的依赖的原型。
Car.prototype.doors=4;
Car.prototype.drivers=new Array("china","中国");
Car.prototype.showColor=function(){alert(this.color);}
//test;
var oCar1=new Car();
var oCar2=new Car();
oCar1.push("操死小日本");
alert(oCar1.drivers);//output "china,中国,操死小日本"
alert(oCar2.drivers);//output "china,中国,操死小日本"
由于drivers是引用值,所以Car的两个实例都指向一个值。
这与真正的面向对象还是一段距离。再次进行改造。
5) 混合的构造/原形方式。
可能你已经想到,既然用prototype属性能让对象属性外置,那何不把对象的属性放在构造函数内,而把方法用prototype引用到构造函数外内。这样就可以解决所有问题了:
function Car(sColor,iDoors)
{
this.colors=sColor;
this.doors=iDoors;
this.drivers=new Array("东京大屠杀吧!");
}
Car.prototype.showColor=function()
{alert(this.color);}
var oCar1=new Car("red",4);
var oCar2=new Car("blue",4);
oCar1.drivers.push("给东京来个原子炸");
alert(oCar1.drivers)//output "东京大屠杀吧,给东京来个原子炸";
alert(oCar2.drivers)//output "给东京来个原子炸".
由于使用了原型方法,所以仍可以用instanceof来检查对象的类型,详情见上。只要是用了原型的方式实现类则可用instanceof来检查对象,而什么是原型,用了prototype的就是了。
好了到现已经差不多了吧,没有了多个函数版本造成的内存浪费问题,没有属性共享问题。和面向对象已经很接近了。但是美中不足的是函数必须要写到类之外,如果知道C++的应该知道,它可以把方法内置,也可以写在类内。写在外面让人阅读起来很费劲。所以继续改造。
6)动态原型法。它与混合的构造/原型差不多,只是函数的实现位置转到类内部。
function Car(sColor,iDoors)
{
this.colors=sColor;
this.doors=iDoors;
this.drivers=new Array("东京大屠杀吧!");
//注意这里
if(typeof Car._initialized=="true")
{
Car.prototype.showColor=function()
{alert(this.color);}
Car._initialized=true;//以_开头的属性被大家公的一种私有属性的表示方法,但是只是表示上的私有,而它是public的。
}
}
OK。到现在为止,用javascript实现类,有几种方式已经介绍完了。欢迎交流。
相关文章推荐
- 浅谈Javascript如何实现匀速运动
- 浅谈Javascript如何实现匀速运动
- javascript 中的面向对象实现 如何封装
- 浅谈javascript对象、如何实现继承、jQuery方法的扩展(jquery插件)
- JavaScript如何实现面向对象和继承机制?
- javascript中不提供sleep功能如何实现这个功能
- 如何在 JavaScript 中实现拖放
- JavaScript的lazyload延迟加载是如何实现的
- JavaScript如何实现跨域访问(CORS)?
- 如何用JavaScript实现旋转木马
- JavaScript面向对象的方法实现继承:call方法
- JavaScript面向对象-基于原型链和函数伪装组合的方式实现继承
- Javascript map如何实现
- javaScript采用面向对象的方式实现实现拖拽
- 如何利用JAVASCRIPT实现浮动广告
- javaScript如何实现继承(javaScript实现继承的五种方式)
- Javascript面向对象实现的几种方法
- javascript面向对象中继承实现?
- 如何写出好的 JavaScript —— 浅谈 API 设计