在VBScript中使用类的方法
前言
首先,在我进入实质性主题并解释如何建立类之前,我希望保证你知道“对象”。虽然你可以在程序中使用对象而不用知道其正确的规则,但我并不建议如此!对于对象的初学者,接下来的部分将让你了解其概念及内容。已经了解面向对象编程(OOP)的读者可以跳过这章节。
导论
“对象是什么?”——对象通常代表某种实体,主要是一个变量和函数的集合。
“实体是什么?”——字面上说,实体是一个“事物”,我的意思是一个概念或者任何一个物体。例如,一辆汽车是一个实体,因为它是一个物体。你公司销售部门销售产品也是一个实体,当然,你也可以将其拆开来看,销售人员、客户、产品等都是实体。
让我们更深入的来看“销售”这个实体(对象)。为了使你更准确地有一个销售的“映像”,你需要知道客户买了什么,是哪个客户,谁是销售人员等等……这看来是一个简单的事件,但假设所有信息是存储在单独的数据库表中的,那么当你需要获得某个销售过程所有相关信息时,你必须在你的数据库中做多次独立查询,再将所有的数据集拢。有没有更简便的办法而一次获得销售的所有信息呢?“对象”。
在对象中,你可以植入代码以从其他表中获得数据,你也可以保存对象属性的所有信息,这样,你可以轻松地使用代码管理你的销售数据。例如:
'Open the database connection
Set objConn = Server.CreateObject("ADODB.Connection")
objConn.Open "MyDSN"
'Create the recordset object
Set objRS = Server.CreateObject("ADODB.Recordset")
'Define the SQL query
strComplexSQLQuery = "SELECT C.Name, S.Name FROM Customers C, " & _
"Salespeople S, Sales Sl WHERE Sl.CustomerID=C.ID AND " & _
"Sl.SalespersonID=S.ID AND Sl.ID=" & strIDOfThisSale & ";"
'Open the recordset
objRS.Open strComplexSQLQuery, objConn, adOpenForwardOnly, _
adLockReadOnly, adCmdText
'Take the customer and sales person names from the recordset
strCustomerName = objRS(0)
strSalesPersonName = objRS(1)
'Tidy up the objects
objRS.Close
objConn.Close
Set objRS = Nothing
Set objConn = Nothing
'Output the data
Response.Write "This sale was made by " & strSalesPersonName & _
" to " & strCustomerName
可以使用“对象”来替代:
'Create the "Sale" object
Set objSale = New Sale
'Lookup the correct sale
objSale.ID = strIDOfThisSale
'Output the data
Response.Write "This sale was made by " & objSale.SalesPersonName & _
" to " & objSale.CustomerName
'Tidy up the objects
objSale.Close
Set objSale = Nothing
如果你使用“Sale”对象做比打印更多的事,可以让你省去很多的打字时间。
计算中,对象包括“属性”和“方法”。属性主要是储存在对象中的一个变量,其用法与变量相同。唯一的区别在于参数赋值为:strMyVar = "This is a string variant", 而对象属性为 objObject.Property="This is a string variant"。这点非常简单而有用处。方法可以理解为植入对象中的函数与过程,可以使用strMyVar = objObject.MethodName(strMyVar)来代替strMyVar =FunctionName(strMyVar)。写法不同,但功能相同。属性的一个例子是对象Response中的ExpireAbsolute,Response.ExpiresAbsolute = CDate("1 September 1999")。方法的一个例子是对象Response中的Write方法,Response.Write "Hello world!"。
VBScript的一个新特性就是其可以创建新的对象而不需要求诸于花销时间都极大的编译器。我将向读者展示如何创建对象的类,并希望提供一个良好的开端。
创建对象
在VBScript中创建对象类型(类)时,你首先要知道,这真的很容易!我在一个下午自学,只是阅读了Microsof VB Script 的参考书,但必须承认,这书不是最容易阅读的文档。
初学者需要安装VBScript 5.0引擎,可以在Microsoft's Scripting Site下载。
我们来看代码。类的定义与函数和子过程非常类似。起始行为Class ,结尾是End Class,所有的对象定义写在中间部门。现在我们可以用所学的来建立第一个类,不实现任何功能的类。
Class 4GuysTestObject
End Class
这看上去不是那么回事,但当你写入下面的代码后,你将创建一个对象的实例:
Dim objTestObject
Set objTestObject = New 4GuysTestObject
Set objTestObject = Nothing
显然,我们现在还不能用对象做任何事,现在我将解释如何在对象中定义属性和方法。
使用对象可以做的最基础的,是建立一组数据。例如,假如要将时间、日期及视频程序标题建立在一起,你可以创建一个包含属性“StartTime”, “ProgramDate”和“ProgramTitle”的对象。代码如下:
Class TVProgram
Public StartTime
Public ProgramDate
Public ProgramTitle
End Class
Dim objTVShow
Set objTVShow = New TVProgram
objTVShow.StartTime = CDate("17:30")
objTVShow.ProgramDate = DateSerial(1999,9,17)
objTVShow.ProgramTitle = "The Jerry Springer Show"
Response.Write objTVShow.ProgramTitle & " is on at " & _
objTVShow.StartTime & " on " & objTVShow.ProgramDate
代码工作的方式是,我们定义StartTime,ProgramDate和ProgramTitle为类TVProgram的属性。这样,这些属性就像其他变量一样来处理,没有设置值则不会执行代码。属性名字前的Public字段有其真实含义,而且非常重要。如果你不特指一个方法或属性为public或private,系统默认值为public,但最好养成定义任何值的良好书写习惯(也方便你之后自己的阅读)。
上面程序的结果大致如下(决定于你的本地服务器配置):The Jerry Springer Show is on at 5:30pm on 17/09/99.
我在英国,所以日期现实如上。不论你跑什么工程,它的效果都不错,但只有你开始使用其他对象的功能,为你可能需要的所有信息和功能,创建一个完美的接口,以支持你所建对象包围的实体,你才会体会到对象的真正实力。
现在,如果你不喜欢上面例子显示日期的方法,而希望以同一种格式现实日期,也没有不要在引用每个ProgramDate属性时加FormatDateTime(),你只需要将此类代码植入属性本身。
这样需要用另一种方法定义属性。同样,我们将使用ProgramDate为外部可见属性,但因为ProgramDate属性将成为一个函数而不是静态值,我们将实际日期保存在另一个属性中internal_ProgramDate。
Class TVProgram
Public StartTime
Public internal_ProgramDate
Public Property Get ProgramDate
ProgramDate = Day(internal_ProgramDate) & _
" " & MonthName(Month(internal_ProgramDate)) & _
" " & Year(internal_ProgramDate)
End Property
Public ProgramTitle
End Class
Dim objTVShow
Set objTVShow = New TVProgram
objTVShow.StartTime = CDate("17:30")
objTVShow.internal_ProgramDate = DateSerial(1999,9,17)
objTVShow.ProgramTitle = "The Jerry Springer Show"
Response.Write objTVShow.ProgramTitle & " is on at " & _
objTVShow.StartTime & " on " & objTVShow.ProgramDate & "."
程序的结果如下:
The Jerry Springer Show is on at 5:30pm on 17 September 1999
我们来分析一下(2)中的程序:
Class TVProgram
Public StartTime
Public internal_ProgramDate
Public Property Get ProgramDate
ProgramDate = Day(internal_ProgramDate) & _
" " & MonthName(Month(internal_ProgramDate)) & _
" " & Year(internal_ProgramDate)
End Property
Public ProgramTitle
End Class
Dim objTVShow
Set objTVShow = New TVProgram
objTVShow.StartTime = CDate("17:30")
objTVShow.internal_ProgramDate = DateSerial(1999,9,17)
objTVShow.ProgramTitle = "The Jerry Springer Show"
Response.Write objTVShow.ProgramTitle & " is on at " & _
objTVShow.StartTime & " on " & objTVShow.ProgramDate & "."
当调用对象的属性ProgramDate时,实际上执行了函数ProgramDate,即如上定义的函数,而很快你也将习惯这种在声明部分使用Public或Private关键字的方式。关键字“Property”,告知了编译器如同调用属性一样在外部调用函数。接着的“Get”,表明该函数是输出还是获得一个值。
Get的意思是“允许外部代码去‘获取’一个值”,与其类似的关键字还有“Let”和“Set”,但这两个比较复杂,因而我们以后再讨论。
接下去的代码看来有点难度的,给objectname.internal_ProgramDate赋值并通过objectname.ProgramDate来调用它。如果可以使用相同关键字同时为其赋值并获得它的值不是更好吗?当然,那也可以。
如果定义Get和Let属性的名称相同,可以将它们当作对象相同的属性,但这只限于它们定义了相同数量的成员。(以下代码看来不太相同,仅作为实例参考)
Class TVProgram
Public StartTime
Public internal_ProgramDate
Public Property Get ProgramDate
ProgramDate = Day(internal_ProgramDate) & " " _
& MonthName(Month(internal_ProgramDate)) & _
" " & Year(internal_ProgramDate)
End Property
Public Property Let ProgramDate(ByVal varDateIn)
internal_ProgramDate = CDate(varDateIn)
End Property
Public ProgramTitle
End Class
Dim objTVShow
Set objTVShow = New TVProgram
objTVShow.StartTime = CDate("17:30")
objTVShow.ProgramDate = "17 Sept 99"
objTVShow.ProgramTitle = "The Jerry Springer Show"
Response.Write objTVShow.ProgramTitle & " is on at " & _
objTVShow.StartTime & " on " & objTVShow.ProgramDate & "."
以上代码中Let的声明部分看来似乎是一个多余的元素,当我第一次看到时研究了很长时间。每次我使用“0”作为变量用在每个属性上,我总是得到这个错误信息,“元素数量必须相等”。“它们确实相等!”抓狂之后,我回过头去看程序才觉得自己的愚蠢!:)
原因是,当你试图为ProgramDate赋值时,你会使用这样一行程序:objTVShow.ProgramDate = dtmMyDate
为了方便,等号右边的值(这里指dtmMyDate)作为了一个程元赋给了函数。因此编译器可能会认为在Get ProgramDate行有0程元,而Let ProgramDate却多一个!分配的值总是被略过而作为属性的最后一个程元,所以即使你使用其他程元,所赋的值总是作为最后一个程元。
现在看程序。无论通过ProgramDate设置日期为文本形式,还是用internal_ProgramDate译成日期变量,程序都没有问题。但能不能只使用一个入口呢?
如果internal_ProgramDate只能在内部有效,而使用Let ProgramDate检查传输的数据类型,我们就可以作出选择。例如:
Class TVProgram
Public StartTime
Private internal_ProgramDate
Public Property Get ProgramDate
ProgramDate = Day(internal_ProgramDate) & " " & _
MonthName(Month(internal_ProgramDate)) & _
" " & Year(internal_ProgramDate)
End Property
Public Property Let ProgramDate(ByVal varDateIn)
If IsDate(varDateIn) Then
internal_ProgramDate = varDateIn
Else
'Place some error handling code in here.
End If
End Property
Public ProgramTitle
End Class
并同样声明StartTime属性:
Class TVProgram
Private internal_StartTime
Public Property Get StartTime
StartTime = Hour(internal_StartTime) & ":" _
& Minute(internal_StartTime)
End Property
Public Property Let StartTime(ByVal varTimeIn)
If IsDate(varTimeIn) Then
internal_StartTime = varTimeIn
End If
End Property
Private internal_ProgramDate
Public Property Get ProgramDate
ProgramDate = Day(internal_ProgramDate) & " " _
& MonthName(Month(internal_ProgramDate)) & _
" " & Year(internal_ProgramDate)
End Property
Public Property Let ProgramDate(ByVal varDateIn)
If IsDate(varDateIn) Then
internal_ProgramDate = varDateIn
End If
End Property
Public ProgramTitle
End Class
现在的代码离我们想要的还是有些不太实用,我们将在其他页使用类TVProgram,因此最好将其独立定义,以便所有也面都可以调用。我们将在第四部分讨论这点。
现在的代码离我们想要的还是有些不太实用,我们将在其他页使用类TVProgram,因此最好将其独立定义,以便所有也面都可以调用。创建一个ASP页面,并命名为TVProgramClass.asp,我们在其中定义类TVProgram。
--TVProgramClass.asp--
<%
Class TVProgram
Private internal_StartTime
Public Property Get StartTime
StartTime = Hour(internal_StartTime) & ":" & Minute(internal_StartTime)
End Property
Public Property Let StartTime(ByVal varTimeIn)
If IsDate(varTimeIn) Then
internal_StartTime = varTimeIn
End If
End Property
Private internal_ProgramDate
Public Property Get ProgramDate
ProgramDate = Day(internal_ProgramDate) & " " & MonthName(Month(internal_ProgramDate)) & " " & Year(internal_ProgramDate)
End Property
Public Property Let ProgramDate(ByVal varDateIn)
If IsDate(varDateIn) Then
internal_ProgramDate = varDateIn
End If
End Property
Public ProgramTitle
End Class
%>
这样就可以在任何ASP中调用我们定义的类了,语法如下:
<!-- #include virtual="TVProgramClass.asp" -->
<%
Dim objTVShow
Set objTVShow = New TVProgram
objTVShow.StartTime = CDate("17:30")
objTVShow.ProgramDate = DateSerial(1999,9,17)
objTVShow.ProgramTitle = "The Jerry Springer Show"
response.write objTVShow.ProgramTitle & " is on at " & objTVShow.StartTime & " on " & objTVShow.ProgramDate & "."
%>
这里有一个建议。如果你重命名你的包含文件.asp,并保证所有重要代码都在<% ... %>中,那么就算有人猜到了你包含文件的文件名,也没办法看见里面的内容!
评论:
VBScript类在封装的层面上,还是有不少好处的,增加了代码的可读性与可维护性以及清晰度,但是,没有继承和重载等特性,并不是真正意义上的OOP。没有集合,但是据说可以用Scripting.Dictionary,据说更好用、更快。不过,感觉总是鸡类(肋)。
vbs类的使用方法
类的结构,
class类名称
endclass
调用方法setmyclass=new类名称
中间类里面的代码,
类模块的事件过程。
PrivateSubClass_Initialize()
这里写上类实例化的时候执行的代码。
endsub
PrivateSubclass_terminate()
这里是类注销的时候自动执行的代码,
endSub
上面两个子程序的名称是规定的,
如果改了名称,就会无效。
1、变量
2、函数(Function)
3、属性(Property)
4、方法(SUB)
一、对象的访问限制,分为公有和私有,公有的(public)可以让外部访问,私有的(Private)外部不能访问,
上面几种角色都可以定义为公有或私有。
定义变量
publicmystr,mystring
这样就定义了两个公有的变量,调用方法myclass.mystr
反之
Privatemystr,mystring
则为私有的变量,外部不能访问的。
函数
PublicFunctionCheckstr(Str)
IfIsnull(Str)Then
CheckStr=""
ExitFunction
EndIf
CheckStr=Replace(Str,"'","''")
EndFunction
这是一个公有函数,外部可以访问的,调用方法myclass.Checkstr(Str)
反之如果为私有的,则用Private取代public
3、属性(Property)
属性分两种,一种是只写属性,一种是只读属性。
也可以为公有或私有,现在以公有为例子。
这是一个只写的属性
PublicPropertyLetValue(ByValvNewValue)
Dimtmpstr
tmpstr=vNewValue
tmpstr=split(tmpstr,"@@@")
html=split(tmpstr(0),"|||")
Strings=split(tmpstr(1),"|||")
pic=split(tmpstr(2),"|||")
EndProperty
这是一个只读的属性
PublicPropertyGetTodayNum
TodayNum=Application(Forum_sn&"_Dv_setup")(9,0)
EndProperty
如果要有读写的属性那么
PublicPropertyGetTodayNum
TodayNum=Application(Forum_sn&"_Dv_setup")(9,0)
EndProperty
PublicPropertyLetTodayNum(ByValvNewValue)
TodayNum=vNewValue
EndProperty
这样写TodayNum就具有读写的属性了,
方法,也以公有为例,
PublicSubTrueCheckUserLogin()
代码
endsub
以下为一个简单的类的的例子:
Classcls_templates
Publichtml,Strings,pic
PrivateSubClass_Initialize()
endsub
PrivateSubclass_terminate()
endsub
PublicPropertyLetValue(ByValvNewValue)
Dimtmpstr
tmpstr=vNewValue
tmpstr=split(tmpstr,"@@@")
html=split(tmpstr(0),"|||")
Strings=split(tmpstr(1),"|||")
pic=split(tmpstr(2),"|||")
EndProperty
EndClass
使用VBScript中的类组织开发
当在一个机构内部创建Web应用程序时,有时候你会发现你自己从一个应用程序中复制和粘贴相同的代码到其它的应用程序中。如果你能够固化所有这些过程到一个好用的小包(package)中,其后你就可以在整个域中使用它了,这样会方便很多。
同时,如果你有一个重复使用的过程,创建一个类包含你的过程可能会比较有用。使用类组织你的代码有一些优点:它使得你的代码容易阅读和调试;你可以将你的类轻松的移值到一个Web服务中;你为其它开发人员提供一个抽象工具(从而节省了时间和资金);同时在一个项目的开发阶段你还保留了灵活性。
当把你的通用过程组织到一个类的时候,你创建一级抽象,允许你在几乎所有代码中实现这些过程。例如,假设在你创建的每个Web应用程序中,你者需要初始化用户信息。这个初始化过程包括在用户登录到你的应用程序时根据用户凭证所做的一些数据库服务器连接。如果你在每个应用程序中都需要完成这个任务的话,那么将你的代码固化到一个类中相当有意义。
下面是实现方法:
DimMyToolbox
SetMyToolbox=NewCToolbox
Response.Write"UserName:"&MyToolbox.UserName&"<BR>"&vbCrLf
Response.Write"UserPhone:"&MyToolbox.UserPhone&"<BR>"&vbCrLf
SetMyToolbox=Nothing
ClassCToolbox
Privatem_conn,m_rs
Privatem_username,m_userphone
PublicPropertyGetUserName()
UserName=m_username
EndProperty
PublicPropertyGetUserPhone()
UserPhone=m_userphone
EndProperty
PrivateSubClass_Initialize()
Setm_conn=Server.CreateObject("ADODB.Connection")
m_conn.ConnectionString="Someconnectionstring"
m_conn.Open
Setm_rs=Server.CreateObject("ADODB.Recordset")
Setm_rs.ActiveConnection=m_conn
m_rs.Open"SELECT*FROMUsersWHEREuserid='"&
Request.ServerVariables("LOGON_USER")&"'"
IfNotm_rs.EOFThen
m_username=m_rs.Fields("username")
m_userphone=m_rs.Fields("userphone")
EndIf
EndSub
PrivateSubClass_Terminate()
OnErrorResumeNext
m_rs.Close
Setm_rs=Nothing
m_conn.Close
Setm_conn=Nothing
EndSub
EndClass
从例子中你可以看到,UserName和UserPhone属性在类初始化之后就会有值。你可以将这个类的代码放到ASP代码的最后。然后在其余的代码中其功能就可以在使用,不用实例化ADO对象,进行数据库调用和之后的清理。而且,如果你使用的是MicrosoftVisualInterDev,那么类中定义的属性和方法可以通过智能感知(IntelliSense)使用。
智能感知只对一级属性和方法有效,所以如果你创建一个类返回其它ASP类的对象,那么InterDev就不会提供可用的方法和属性。
下面的代码是一个类的骨架:
ClassMyClass
PrivateSubClass_Initialize()
EndSub
PrivateSubClass_Terminate()
EndSub
EndClass
使用这个基本信息,一个类被声明,并且可以使用它来创建对象。但是这个类的对象没有功能——它们是无用的东西。类的方法从PublicSub或者PublicFunction声明构建(Subs没有返回值,而Function有返回值)。
有两个方法可以暴露属性:既可以在类的全局上下文中使用PublicVarName,也可以使用PublicPropertyGet/Set/Let。如果你需要一个只读属性,那么只要简单地使用一个PropertyGet声明即可。所有其它声明为Private的Properties,Subs或者Functions只有在实例化的对象才可用。在类的全局上下文中声明为Private的变量是成员变量。
创建类的另外一个好处是你可以轻易的将这个类声明移值到Web服务中。因为这是很多开发人员前进的方向,你可以通过使用类创建面向对象的代码先行一步。当你移值这些类声明到一个Web服务时,你不需要重写所有的放置了那段代码的ASP代码。所要做的唯一的改变就是你的对象的实例化。
我发现创建这个抽象的最大的优点是可以使用其它Web开发者的帮助。因为对于很多开发人员来说在每个不同的实现中重复创建相同的代码效率相当低,所以这个方法为每个开发人员提供了一个抽象工具。这就允许每个开发人员将精力更多地集中在当前工作的功能上面,而不是花费时间重写他们已经开发过的代码上面。
如果你奇怪为什么我不提供一个COM对象来处理这个功能,那是因为它会把你锁定到细节设计中。通过在ASP中动态地创建类,你可以不用重新编译和发布就能够对类做出更改。在类固定之后,再将它移值到COM、Windows脚本组件(WSC)或者一个Web服务中,但是在开发阶段还是灵活一些好。
由浅到深了解JavaScript类
类是什么?
许多刚接触编程的朋友都可能理解不了类,其实类是对我们这个现实世界的模拟,把它说成“类别”或者“类型”可能会更容易理解一些。比如“人”这种动物就是一个类,而具体某一个人就是“人”这个类的一个实例,“人”可以有许多实例(地球人超过六十亿了),但“人”这个类只有一个。你或许会说那男人和女人不也是人么?怎么只能有一个?其实这里要谈到一个继承的东西,后边才讲,请继续看下去。
如何建立一个类?
在C++中是以class来声明一个类的,JavaScript与C++不同,它使用了与函数一样的function来声明,这就让许多学Jscript的朋友把类与函数混在一起了,在Jscript中函数与类确实有些混,但使用久了自然而然会理解,这篇文章是针对想进攻面向对象编程的朋友而写,就不打算一下子讨论得太深了。
请看下边这个类的定义:
functionWuYouUser()
{
this.Name;//名字
}
上边的代码定义了一个WuYouUser(无忧用户)类,它有个属性:Name(名字)。Name就是WuYouUser类的一个属性。
一个类有固定的属性,但类的实例却有不同的属性值,就像我是属于“人”这个类的,性别是男,而我有一个女同学,她也属于“人”类,但她的性别属性值却为女。
那么如何声明某个类的一个实例呢?非常简单:
varWo=newWuYouUser();//实例一:“我”
varBiyuan=newWuYouUser();//实例二:“碧原”(Biyuan哥,不好意思。。。嘿嘿)
类的属性
这个Wo(我)就是WuYouUser类的一个实例,它拥有WuYouUser给它的一切:Name属性、Sex属性以及Age属性,我们可以这样子来设置它的属性:
Wo.Name="泣红亭";
很简单是不是?试着运行
window.document.write(Wo.Name);
看看,是不是输出了我的名字:泣红亭?
同样设置一下碧原兄的属性
Biyuan.Name="碧原";
运行
window.document.write(Biyuan.Name);
可以看到输出了"碧原",也就说明了Biyuan与Wo同样是WuYouUser类的实例,但却是不同的实体,具有不同的属性值。
属性是可以设置默认值的,无忧里都有记录大家各自发了多少贴子,我们也同样给WuYouUser类添加一个发贴数量的属性ArticleCount
functionWuYouUser()
{
this.Name;//名字
this.ArticleCount=0;
}
一个无忧新用户刚注册完之后他的发贴数量为0,在上边的代码中可以看到直接给属性ArticleCount设置值为0。
可以运行一下这样的代码:
varWo=newWuYouUser();
window.document.write(Wo.ArticleCount);
可以看到输出了0,说明ArticleCount属性被我们成功设置默认值为0
类的方法
方法这个词不大好理解,我觉得说成行为会更容易理解。一个人具有许多共同的行为,比如睡觉、吃饭、走路等等,现在我们给WuYouUser类添加一个发贴的方法。
functionWuYouUser()
{
this.Name;
this.ArticleCount=0;
this.NewArticle=function()
{
/*
*
*具体如何发贴我们大家都知道,不就是打打字,加加图片再按一下保存之类的按钮么?
*关于具体如何发贴的代码没有必要在这里写出来,我们要了解的仅仅是方法的定义与使用
*我们在这里实现一个最简单的功能,也是很重要的功能:给我们的发贴数量加上1!
*注意:恐龙等级就是这样加出来的,因此呀……大家狂发贴吧。。。
*/
this.ArticleCount++;
}
}
既然定义好了这个方法,我们来试试效果如何:
varWo=newWuYouUser();
Wo.NewArticle();
document.write(Wo.ArticleCount);
可以看到输出了1,说明我们发贴成功了!真是有历史纪念意义的一刻,离恐龙等级又近一步了。
静态属性
静态属性又称公共属性,它不属于某个类的实例,而是直接属于某个类。
比如说无忧用户有一个属性:注册用户的数量,它是属于整个无忧用户的,而不是属于泣红亭或者谁的
静态属性的声明方法是:
类名.prototype.属性名=属性值;
比如给WuYouUser类定义一个注册用户的数量Count:
WuYouUser.prototype.Count=0;
那么如何读取它呢?有两种方法:
1.直接用WuYouUser.prototype.Count
2.使用Wo.Count
这两者没有区别,都是得到0
虽然读取方法可以有两种,但在改变它的时候却得特别小心了,请看下边代码
varBiyuan=newWuYouUser();
WuYouUser.prototype.Count++;
document.write(Wo.Count);
document.write(Biyuan.Count);
你会发现两者的Count属性都是1,也就是说WuYouUser.prototype.Count改变了会影响到各个实例的相应属性,其实原理就是Wo、Biyuan的Count属性与WuYouUser.prototype.Count根本就是同一个!
现在来看另外一段代码:
varBiyuan=newWuYouUser();
Biyuan.Count++;//特别注意一下这里,这是直接改变Biyuan的Count属性
document.write(Biyuan.Count);//输出1
document.write(WuYouUser.prototype.Count);//输出0
document.write(Wo.Count);//同样输出0,为什么?
可以看到如果直接修改实例的静态属性值,那么会出现其它实例甚至类的静态属性与它不同步了?这是因为直接修改的时候,该实例会生成一个属于该实例的属性Count,这个时候Biyuan.Count不再与WuYouUser.prototype.Count是同一个了,也不与Wo.Count是同一个,这个Count属性是属于Biyuan自己所有的,以后改变了它也只是影响它自己而已。
因此如果不是特别的需要,建议不管在读取还是赋值的时候,都统一使用WuYouUser.prototype.Count这样的方式,以做到万无一失!
静态方法
与静态属性相似,它也有个另称:公共方法,同样属于类本身的。
静态方法的定义方式是:
类名.方法名=function(参数1,参数2...参数n)
{
//方法代码
}
我们现在就来定义一个无忧用户类的注册新用户静态方法:
WuYouUser.prototype.AddOne=function()
{
//***同样具体代码不写出来,给静态属性Count增加1,表示注册用户数量又多一个
WuYouUser.prototype.Count++;
}
现在我们来看看如何用它,同样有两种方法:
1.直接使用WuYouUser.prototype.AddOne()
2.使用某实例的AddOne()
这两种方法没有什么不同:
varWo=newWuYouUser();
varBiyuan=newWuYouUser();
document.write(WuYouUser.prototype.Count);//0
Wo.AddOne();
document.write(WuYouUser.prototype.Count);//1
document.write(Wo.Count);//1
document.write(Biyuan.Count);//1
WuYouUser.prototype.AddOne();
document.write(WuYouUser.prototype.Count);//2
document.write(Wo.Count);//2
document.write(Biyuan.Count);//2
可以看出不管是使用Wo.AddOne()还是WuYouUser.prototype.AddOne()效果都是一样的,都是给WuYouUser.prototype.Count加上1
现在再看一段代码:
functionNewClass()//由于上边的WuYouUser类不合适当这个例子的代码,我声明了一个新类NewClass
{
this.Name="泣红亭";//这里默认值为我的名字
}
NewClass.prototype.ChangeName=function(NewName)
{
this.Name=NewName;
}
varWo=newNewClass();
Wo.ChangeName("郑运涛");//我的真名
可以看到Wo.Name确实已经变成了"郑运涛",这个方法似乎是可以用的,但里边是不是内有天机呢?
再看下边的代码,类的定义以及ChangeName的定义我们照样,但改变一下下边的代码:
NewClass.prototype.ChangeName("郑运涛");
document.write(NewClass.Name);//undefined,即未定义
document.write(NewClass.prototype.Name);//郑运涛
varWo=newNewClass();
document.write(Wo.Name);//泣红亭
可以看到我们并没有定义NewClass.prototype.Name这个静态属性,但编译器给我们自己加了一个。
可是再看下边输出Wo.Name,它并不是为"郑运涛",而是原来的默认值"泣红亭",说明了什么?
其实很简单,看一下NewClass的定义里已经有Name这个属性,因此Wo也有自己的Name属性,它跟NewClass.prototype.Name并不是同一个的,因此就还是那样子。
那为什么前一个例子运行了Wo.ChangeName("郑运涛")却能够实现改变Wo.Name属性呢?其实在这里跟改变Wo.Count的值是同一个道理,编译器自动给Wo增加了一个方法ChangeName,这个方法代码与NewClass.prototype.ChangeName一样,但Wo.ChangeName是Wo这个实例所特有的,而非NewClass.prototype.ChangeName!
分析可知道在静态方法里尽量不要使用this这样的关键字来引用实例本身的属性,除非你有特别的目的,而且能够清楚地明白这里边的运行机制!
如果真的需要在静态方法里使用this,可以直接把this当作参数传进去:
NewClass.ChangeName=function(This,NewName)//注意这里是This,不是this
{
This.Name=NewName;
}
构造函数
一个类在初始化的时候其实也是一个函数的执行过程,这个函数就是构造函数,我们看一下下边的代码:
functionWuYouUser()
{
this.Name="泣红亭";//默认定义为泣红亭
alert(this.Name);
}
varWo=newWuYouUser();//可以看到出现一个窗口显示泣红亭三个字
可以看出类的定义不仅仅是定义了它的属性与方法,还同时可以加入一些代码,而这些代码就是该类的构造函数的代码,在实例声明过程中被执行!
其实说起来,类的属性与类的方法都是在构造函数里执行定义的,看下边的代码:
functionWuYouUser()
{
this.Name="泣红亭";
return;
this.Sex="男";
}
varWo=newWuYouUser();
document.write(Wo.Name);//泣红亭
document.write(Wo.Sex);//undefined,即未定义
看得出什么?Sex属性是在return;之后的,而WuYouUser类的构造函数遇到return即停止运行,换句话说this.Sex="男";这一行是没有被执行,即Sex属性根本没有被定义!
构造函数可以有参数,参数值在声明实例的时候被传入:
functionWuYouUser(Name)
{
this.Name=Name;
}
varWo=newWuYouUser("泣红亭");
document.write(Wo.Name);//泣红亭
构造函数不需要返回值,但如果你设置了返回值,可以把它当成一个函数来使用。
functionSum(a,b)
{
this.a=a;
this.b=b;
returnthis.a+this.b;
}
document.write(Sum(12,23));//输出的是12与23的和35
varObj=newSum(12,23);
document.write(Obj.a)//12
document.write(Obj.b)//23
感觉挺奇妙,对吧?我写这文章写着写着也觉得挺奇妙的,呵呵!
但强烈建议不要把一个类当成一个函数来使用!如果你需要的是一个函数,请直接写成函数而不要写成类,以免搞混了。
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::继承:::::::::::::::::::::::::::::::::::::::::::::::::::
继承这个词在面向对象的编程里是非常重要的,虽然JavaScript并不是真正面向对象的语言,而是跟VB一样是基于对象的语言,它同样提供了继承机制。
文章开头时谈到了男人与女人,这也同样是两个不同的类,但却具有相同的一些属性以及方法,而这些相同的特性是来自“人”这个类的,换句话说男人与女人继承了“人”的所有特性!但是男人与女人却有其不同的地方,编程语言里的继承也一样,一个类A继承了另一个类B,那么类B就是类A的父类,类A就是类B的派生类,也称为子类。比如男人就是人的派生类,而人就是男人的父类。最高一级的类称为基类,想象一下就可以明白,男人继承自人,男孩继承自男人,人就是男孩的基类,男人就是男孩的父类。
>>>>>>>>>>>>>>>>>>>>
题外:多重继承
这里再涉及一个多重继承的话题,但如果你仅仅是学JavaScript的话就没有必要看下去,因为JavaScript不提供多重继承,准确一点说没有一种简单而标准的方法来实现多重继承(其实是有办法实现的,只不过麻烦了一点,而且确实没有必要)。
在C++中是有多重继承的概念的,这里是讨论JavaScript,因此不打算讲,只是说说它的一点点思想以供参考。
在上边男孩的继承问题中,男孩其实不仅仅是继承自男人,还继承自孩子(有男孩子,也有女孩子)这个类,因此,它同时继承了两个类:男人与男孩,这就是所谓的多重继承。
好,这个问题打住,我们还是回归主题。
>>>>>>>>>>>>>>>>>>>>
先看第一个类的定义:
functionA()
{
this.Name="泣红亭";
alert(this.Name);
}
这个类定义了一个属性Name,默认值为"泣红亭"
现在看第二个类的定义:
functionB()
{
this.Sex="男";
alert(this.Sex);
}
定义了一个属性Sex,默认值为"男"
继承的方式就是子类.prototype=new父类();
现在我们来让B类继承A类:
B.prototype=newA();
运行这一段代码:
varObj=newB();//首先打开警告窗口显示"泣红亭",再显示"男"
可以从上边的结果看出B类继承了A类,拥有了A类的属性Name,并且执行了A类的构造函数,而且A类的构造函数在B类的构造函数执行之前执行。因此我们利用这个可以实现重写父类的方法以及重设置父类某属性的默认值:
functionA()
{
this.Name="泣红亭";
this.Show=function()
{
alert("这是A类的Show方法");
}
alert(this.Name);
}
functionB()
{
this.Name="郑运涛";
this.Show=function()
{
alert("这是B类的Show方法");
}
alert(this.Name);
}
varObj=newB();
Obj.Show();
结果出现了三次警告窗口,第一个内容为泣红亭,是执行A类的构造函数里的alert(this.Name),那时候Name属性值还为"泣红亭",因为B类的构造函数还没执行,第二次内容为"郑运涛",这是B类里的alert(this.Name),因为B类的构造函数里给Name重赋值为"郑运涛"。最后是调用了Obj.Show(),执行了不是A类的Show方法里的Show(显示"这是A类的Show方法"),而是执行了B类的Show(显示"这是B类的Show方法"),很明显Show方法被重写了。
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
类作为一个对象时的属性与方法(不知道如何简洁地表达,因此用了这么长的题目)
不知道在这里谈这个话题是否有点混人耳目,但又觉得不谈这篇文章就不算完整,因为文章目的就是要让人搞清楚类的方方面面。
看了这一小节的题目,或许你会觉得奇怪,类就是类,怎么会“作为一个对象”呢?在JavaScript里,一切都是对象,包括类!对象可以有属性,可以有方法,类也同样可以有,但这个非常容易跟前边说到的静态属性与静态方法搞混了,因此要仔细看清楚两者的分别!
定义一个类:
functionWuYouUser()
{
this.Name="泣红亭";
}
定义类作为一个对象时的属性:
WuYouUser.Url="http://www.51js.com";//静态属性的定义是:WuYouUser.prototype.Url="http://www.51js.com";
varWo=newWuYouUser();
document.write(WuYouUser.Url);//http://www.51js.com
document.write(Wo.Url);//undefined,即未定义!注意这里的未定义
从这里可以看出Url这个属性是WuYouUser自个所有,改变了它与其它类以及它的子类完全无关!
引用类的属性只有一个办法,就是类名.属性名,改变它也一样。
定义类作为一个对象时的方法:
WuYouUser.ChangeUrl=function()
{
this.Url="http://51js.com";
}
你或许会觉得奇怪,这里的this是什么?因为ChangeUrl这个方法是属于对象WuYouUser的,因此this指的就是WuYouUser本身!
可以运行下边的代码试试:
document.write(WuYouUser.Url);//http://www.51js.com
WuYouUser.ChangeUrl();
document.write(WuYouUser.Url);//http://51js.com
明显ChangeUrl直接修改了WuYouUser.Url的值,因此后边才能输出http://51js.com
如果你这一节看不明白,也不要着急,编程嘛,许多东东都只能意会不能言传,而且我又没口才,说不清楚,只要以后多写写代码,多用用类自然而然会体会到这一些,还有可以去看看JSVM的代码,里边几乎每个类都有用到类作为一个对象时的属性与方法。
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
后言
首先感谢你能够有耐心看到这里,我也没想到写了这么多才能够写得像样一点,请别介意。
不管是哪种语言,只要是支持类的,类都在这种语言中占了非常重要的地位,但不是谁都能够掌握它,为了让无忧还没学过类以及对类这个东东还搞不清楚的网友能够清楚一点了解类的概念以及用法,也为了对无忧做点贡献,我写了这篇文章,希望大家能够喜欢。
在你的ASP中使用类(class)
在不入前的一天,当我为了解决一个语法问题来翻阅VBscript文档时,偶然间发现在了下面的一句话:
ClassStatement
Declaresthenameofaclass,aswellasadefinitionofthevariables,properties,andmethodsthatcomprisetheclass.
翻译过来就是......
Class声明
声明一个类的名字,就是定义一些变量,属性,方法来组成一个类
这是真的!!!?VBScript中能用类!?!?不知道能不能用于ASP!?这样的话,我就不是能写出像object一样的ASP程序?!说干就干!实践是检验真理的唯一标准,自个动手吧!
我们常常看到别的程序语言中中都有类的说明,PHP,VB,C++,这个在VBScript中的类的说明,我是第一次听到,我们的日常工作就是网站开发,在这个里面多多少少搞出点经验,像模像样也能自诩为"内行",所以我就来分享一下我所知道的这个新的东东。我们来看看下面的这个代码吧!(window2000+IIS5.0通过测试)
<%
''声明一个名为aspcn的类
Classaspcn
Privateaspcn
''初始化类
PrivateSubClass_Initialize
aspcn="AspcnIsGood!<br>"
EndSub
''定义一个函数
PublicFunctionDoIt()
DoIt=aspcn
EndFunction
''定义一个方法
PublicSubQueryStr(stat)
Response.writestat
EndSub
EndClass
SetHi_aspcn=Newaspcn''定义一个名为Hi_aspcn的aspcn对象实例
response.writeHi_aspcn.DoIt
varstr="AspcnIsCool!<br><fontcolor=red>http://www.aspcn.com</font><br>WelCome!!!"
Hi_aspcn.QueryStrvarstr
%>
这是很简单的一个程序,我们在其中声明了一个名为aspcn的类,建立了一个DoIt函数,一个QueryStr方法,这个程序很简单相信大家能看懂,它的显示如下:
AspcnIsGood!
AspcnIsCool!
http://www.aspcn.com/
WelCome!!!
以后,咱们就可以把我们常用到的程序写成一个类,到时候就用<!--#includefile="xxx.asp"-->来包含进来就行了,这给我们开发程序又提供了新的空间,真是爽啊!和C++一样了,有点回归自然的感觉.
VBSctipt5.0中的新特性
能够在ASP中应用的特性包括了那些由脚本引擎所提供的特性,这意味着VBScript的改进也可在ASP中应用。VBScript的改进如下所述:
1、在脚本中使用类
在VBScript中实现完整的VB类(class)模型,但明显的例外是在ASP服务器端的脚本事件。可以在脚本中创建类,使它们的属性和方法能够和用于页面的其余代码,例如:
ClassMyClass
Privatem_HalfValue‘LocalvariabletoholdvalueofHalfValue
PublicPropertyLetHalfValue(vData)‘executedtosettheHalfValueproperty
IfvData>0Thenm_HalfValue=vData
EndProperty
PublicPropertyGetHalfValue()‘executedtoreturntheHalfValueproperty
HalfValue=m_HalfValue
EndProperty
PublicFunctionGetResult()‘implementstheGetResultmethod
GetResult=m_HalfVaue*2
EndFunction
EndClass
SetObjThis=NewMyClass
ObjThis.HalfValue=21
Response.Write“ValueofHalfValuepropertyis“&objThis.HalfValue&“<BR>”
Response.Write“ResultofGetResultmethodis“&objThis.GetResult&“<BR>”
…
这段代码产生如下结果:
ValueofHalfValuepropertyis21
ResultofGetResultmethodis42
2、With结构
VBScript5.0支持With结构,使访问一个对象的几个属性或方法的代码更加紧凑:
…
SetobjThis=Server.CreateObject(“This.object”)
WithobjThis
.Property1=“Thisvalue”
.Property2=“Anothervalue”
TheResult=.SomeMethod
EndWith
…
3、字符串求值
Eval函数(过去只在JavaScript和Jscript中可用)目前在VBScript5.0中已经得到了支持。允许创建包含脚本代码的字符串,值可为True或False,并在执行后可得到一个结果:
…
datYourBirthday=Request.Form(“Birthday”)
strScript=“datYourBirthday=Date()”
IfEval(strScript)Then
Response.write“HappyBrithday!”
Else
Response.write“Haveaniceday!”
EndIf
…
4、语句执行
新的Execute函数允许执行一个字符串中的脚本代码,执行方式与Eval函数相同,但是不返回结果。它可以用来动态创建代码中稍后执行的过程,例如:
…
strCheckBirthday=“SubCheckBirthday(datYourBirthday)”&vbCrlf_
&“IfEval(datYourBirthday=Date())Then”&vbCrlf_
&“Response.Write“”HappyBirthday!”””&vbCrlf_
&”Else”&vbCrlf_
&”Response.write“”Haveaniceday!”””&vbCrlf_
&”EndIf”&vbCrlf_
&”EndSub”&vbCrlf
ExecutestrCheckBirthday
CheckBirthday(Date())
…
一个回车返回(如程序中示)或冒号字符“:”可用来分隔一个字符串中的各条语句。
5、设置地区
新的SetLocale方法可以用来改变脚本引擎的当前地区,可正确显示特殊的地区特定字符,如带重音符的字符或来自不同字符集的字符。
StrCurrentLocale=GetLocale
SetLocale(“en-gb”)
6、正则表达式
VBScript5.0现在支持正则表达式(过去只在JavaScript、Jscript和其他语言中可用)。RegExp对象常用来创建和执行正则表达式,例如:
StrTarget=“testtestingtestedattestlatestart”
SetobjRegExp=NewRegExp‘createaregularexpression
ObjRegExp.Pattern=“test*”‘setthesearchpattern
ObjRegExp.IgnoreCase=False‘setthecasesensitivity
ObjRegExp.Global=True‘setthescope
SetcolMatches=objRegExp.Execute(strTarget)‘executethesearch
ForEachMatchincolMatches‘iteratethecolMatchescollection
Response.Write“Matchfoundatposition”&Match.FirstIndex&“.”
Resposne.Write“Matchedvalueis‘”&Match.Value&“’.<BR>”
Next
执行结果如下:
Matchfoundatposition0.Matchedvalueis‘test’.
Matchfoundatposition5.Matchedvalueis‘test’.
Matchfoundatposition13.Matchedvalueis‘test’;
Matchfoundatposition22.Matchedvalueis‘test’.
7、在客户端VBScript中设置事件处理程序
这不是直接应用于ASP的脚本技术,这个新的特性在编写客户端的VBScript时是很有用的。现在可以动态指定一个函数或子程序与一个事件相关联。例如,假设一个函数的名称为MyFunction(),可把这指定给按钮的OnClick事件:
FunctionMyFunction()
…
Functionimplementationcodehere
…
EndFunction
…
SetobjCimButton=document.all(“cmdButton”)
SetobjCmdButton.OnClick=GetRef(“Myfunction”)
这提供了JavaScript和Jscript中的类似功能,函数可以被动态地指定为一个对象的属性。
8、VBScript中的OnErrorGoto0
尽管这个技术早先没有被文档记载,但在现有的VBScript版本中能够使用(有着VB背景并且有好奇心的人可能早已发现这个秘密)。它现在已被记录在文档中,并且在执行OnErrorResumeNext后能够用来“关闭”页面中的定制错误处理。结果是任何后来的错误将引发一个浏览器级或服务器级的错误及相应的对话框/响应。
本文地址:http://www.45fan.com/a/question/70413.html