Javascript出现也不是一天两天了,但近些年之前,一直都只是做一做表单验证,加点花哨的网页特效什么的,顶多算得网页设计的调料 。但是随着应用系统向着网络延伸,Javascript在系统应用中扮演着越来越重要的角色,Jquery、Ext、Dojo等Ajxa框架层出不穷。每一个在浏览器上做开发的程序员都有必要了解一下Javascript语言!
与C++等语言不同的是,Javascript是一种弱类型语言,只有字符串、数值等几种基本的数据类型,并且可以随意转换,由浏览器动态解释执行,这种特性一方面为开发提供了更多的灵活性,另一方面也增加了开发的复杂性!
Javascript是一种基于对象的语言,而不是面向对象的语言。Javascript语言本身定义了字符、数组、日期等一系列对象。在任何地方都可以使用这些对象,但是却没有class关键字,不能定义自己的类和对象。Javascript代码只有以面向过程的方式开发,当代码数量级增大的时候,几乎无法控制所有Javascript代码!但是Javascript是极其灵活的语言,它内部的原生对象链特性提供了足够的灵活度让我们可以模拟出面向对象的特性,抽象、封装、继承、多态,一个也不少!
首先是一个普通的Javascript方法:
function HelloWorld(){return “HelloWorld”;}//定义一个方法
HelloWorld();//调用这个方法
其实上面的代码就已经创建了一个类HelloWorld,然后又创建了这个类的对象,为了让它看起来更像类和对象,可以把上面的代码改造一下:
function MyClass(){return this;}//定义一个类
var Obj = new MyClass();//实例化对象
相同的语法,换一种写法就会发现利用function关键字就可以定义一个类,用对function的调用级可实例化自定义类的对象!既然是类,就应该具备封装性,那么公有属性、公有方法、私有属性、私有方法、构造函数是什么样的呢?
function calculator(a,b){//定义一个类
this.PI=3.14; //公有属性
this.Text="计算器"; //公有属性
this.A; //公有属性
this.B; //公有属性
var m_me=this; //私有属性
var m_Remark="calculator";//私有属性
this.Add=function(){ //公有方法
//公有方法可以调用其它公有属性或方法
return this.A+this.B;
}
this.Sub=function(){ //公有方法
return m_me.SubNum(this.A,this.B);
}
var SubNum=function(a,b){//私有方法
return a-b;
}
var AddNum=function(){//私有方法
//私有方法可以调用私有属性或方法
var X=SubNum(9,6);
/*私有方法不能直接调用公有方法,
为了调用公有方法,则可以使用m_me这个指向类本身的 私有属性即可*/
return m_me.Add();
}
/*其它未封装在公有方法和私有方法中的代码,即为构造函数的 代码,构造代码既可调用公有方法也可调用私有方法,不受限制*/
var TestValue=SubNum(6,5);
}
var Obj = new calculator(100,50);//实例化对象
var X = Obj.Add(); //调用公有方法
var Y = Obj.PI; //调用公有属性
Obj.A=200;
Obj.B=150;
var Z=Obj.Sub();
由this定义的属性或方法就是公有属性或方法,由var定义的属性或方法就是私有方法,不属于私有方法或属性的代码即为构造代码!构造代码将会在对象实例化的时候被执行,而公有和私有方法内定义的代码只有在被调用的时候才会被执行!
构造代码可以访问公有和私有方法或属性,公有方法也可以访问公有和私有方法或属性,但是与其它语言不同的是,Javascript定义的类中,私有方法有独立的作用域,无法通过this关键字访问类,因此也无法直接访问公有方法或属性,只可以访问私有方法或属性,为了在私有方法中访问公有方法或属性,可以定义私有属性var m_me=this;然后通过这个私有属性,间接的访问公有方法或属性!
到此,封装性就差不多了,但是Javascript是动态解释执行的,因此可以在运行中动态的为对象添加属性或方法(公有):
function calculator(){//定义一个类
this.A=1; //定义公有属性
this.Add=function(){ //定义公有方法Add
return this.A++;
}
}
var Obj = new calculator(); //实例化对象
Obj.Add(); //调用公有方法Add
Obj.Sub=function(){ //为Obj对象添加公有方法Sub
return 9-6;
}
var X = Obj.Sub(); //调用公有方法Sub
calculator.prototype.SubNum=function(){//为calculator类定义公有方法SubNum
return 100-50;
}
var Y = Obj.SubNum(); //调用公有方法SubNum
可以直接为对象动态添加属性和方法,也可以用prototype关键字为类添加公有方法,所有的对象都会包含类中新添加的属性方法,因此可以利用此特性扩展Javascript语言内嵌的对象:
String.prototype.trim = function(){//去掉首尾空格
return this.replace(/(^/s*)|(/s*$)/g,"");//将字符串前后空格,用空字符串替代。
}
var Text = " Text Text ";
var NewText = Text.trim();//去掉前后空格
既然可以在类的不同地方或对象上定义属性或方法,那么,如果这些属性或方法同名的话,哪些方法会被隐藏呢?以下是测试代码:
<html> <head></head> <body> <script language="Javascript"> function MyClass(){//定义一个类 this.Hello=function(){ //定义公有方法Hello return "Hello A"; } } var Obj = new MyClass(); var X = Obj.Hello(); alert(X); //结果:Hello A Obj.Hello=function(){ return "Hello B"; } var Y = Obj.Hello(); alert(Y); //结果:Hello B MyClass.prototype.Hello=function(){// return "Hello C"; } var Z = Obj.Hello(); alert(Z); //结果:Hello B Obj.Say=function(){ // return "Say B"; } var YY = Obj.Say(); alert(YY); //结果:Say B MyClass.prototype.Say=function(){ return "Say C"; } var ZZ = Obj.Say(); alert(ZZ); //结果:Say B var Obj2= new MyClass(); var K = Obj2.Hello(); alert(K); //结果:Hello A var KK = Obj2.Say(); alert(KK); //结果:Say C </script> </body> </html>
通过以上测试,就可以看出,为对象添加的属性只会添加在对象本身上,而不会增加到类中;在类的prototype中增加了方法,则所有的对象都增加了此方法!
当以不同的方式为类或对象增加了同名的方法或属性,那么只有一个方法可见,其它方法将被隐藏!可访问性由高到低依次为:对象定义的方法>直接在类中定义的方法>通过prototype为类定义的方法
这里再提一下静态方法,Javascript也可以有静态方法,一切皆是对象,类也是对象,因此也可以为“类”这个对象添加方法属性,实现类的静态方法:
function MyClass(){//定义一个类
this.Add=function(a,b){ //定义公有方法Add
return a+b;
}
}
MyClass.sub=function(a,b){//添加一个静态方法
return a-b;
}
var X = MyClass.sub(100,50);//使用类名直接调用静态方法
一般的语言都首先定义类,然后实例化类生成对象,Javascript也是如此,但是除此之外还可以直接定义对象:
var MyObj ={
this.Text:"我的对象",
this.Hello:function(){
return "Hello";
}
}
使用Json格式即可直接定义对象,因为Json格式就是解释器使用的内部格式。
到此为止,Javascript类的封装性就差不多了,以后再说一说Javascript类的多态与继承性!