ASP 程序
Sub 与 Function 的差别、参数传递、ByVal / ByRef、递归。
Sub
<%
Sub Greet(name)
Response.Write "Hello, " & name & "<br>"
End Sub
Call Greet("Ada")
Greet "Bob" ' 不用 Call 时不能加括号
%>Hello, Ada
Hello, BobWith Call the arguments need parentheses; without it they must not have any. Greet("Bob") is parsed as one expression and only works by luck with a single argument — the most confusing bit of VBScript syntax.
Function
<%
Function Add(a, b)
Add = a + b ' 给函数名赋值就是返回值
End Function
Function IsEven(n)
If n Mod 2 = 0 Then
IsEven = True
Else
IsEven = False
End If
End Function
Response.Write Add(3, 4) & "<br>"
Response.Write IsEven(10) & "<br>"
Response.Write IsEven(7) & "<br>"
%>7
True
FalseA Function returns by assigning to its own name; there is no return. Forgetting the assignment yields an empty value with no error, so assign on every branch.
ByVal 与 ByRef
<%
Sub ChangeByRef(x)
x = x + 1
End Sub
Sub ChangeByVal(ByVal x)
x = x + 1
End Sub
Dim a, b
a = 10 : b = 10
ChangeByRef a
ChangeByVal b
Response.Write a & " / " & b
%>11 / 10VBScript parameters are ByRef by default, so changes affect the caller's variable — the opposite of Java and C#. Write ByVal unless you intend to write back.
递归
<%
Function Fact(n)
If n <= 1 Then
Fact = 1
Else
Fact = n * Fact(n - 1)
End If
End Function
Response.Write Fact(5)
%>120作用域与 Global
<%
Dim pageLevel
pageLevel = "页面级"
Sub ShowIt()
' 过程内能读页面级变量
Response.Write pageLevel & "<br>"
End Sub
Sub LocalDemo()
Dim pageLevel ' 同名局部变量,遮蔽页面级
pageLevel = "过程级"
Response.Write pageLevel & "<br>"
End Sub
ShowIt
LocalDemo
Response.Write pageLevel & "<br>"
%>页面级
过程级
页面级Dim-ing a local with the same name as a page-level variable shadows it silently. Option Explicit does not catch this; only naming discipline (e.g. a g_ prefix) does.Sub
<%
Sub Greet(name)
Response.Write "Hello, " & name & "<br>"
End Sub
Call Greet("Ada")
Greet "Bob" ' 不用 Call 时不能加括号
%>Hello, Ada
Hello, Bob用 Call 时参数要加括号,不用 Call 时不能加——Greet("Bob") 会被理解成「传一个表达式」,只有一个参数时侥幸能过,多个参数就报错。这是 VBScript 里最容易困惑的语法细节。
Function
<%
Function Add(a, b)
Add = a + b ' 给函数名赋值就是返回值
End Function
Function IsEven(n)
If n Mod 2 = 0 Then
IsEven = True
Else
IsEven = False
End If
End Function
Response.Write Add(3, 4) & "<br>"
Response.Write IsEven(10) & "<br>"
Response.Write IsEven(7) & "<br>"
%>7
True
FalseFunction 的返回值靠「给函数名赋值」,没有 return 关键字。忘记赋值时返回空值,不会报错——所以每个分支都要记得赋值。
ByVal 与 ByRef
<%
Sub ChangeByRef(x)
x = x + 1
End Sub
Sub ChangeByVal(ByVal x)
x = x + 1
End Sub
Dim a, b
a = 10 : b = 10
ChangeByRef a
ChangeByVal b
Response.Write a & " / " & b
%>11 / 10VBScript 的参数默认是 ByRef,函数里改了会影响调用方的变量。这和 Java、C# 的默认行为相反,从别的语言转过来最容易踩这个坑。不需要回传时一律写 ByVal。
递归
<%
Function Fact(n)
If n <= 1 Then
Fact = 1
Else
Fact = n * Fact(n - 1)
End If
End Function
Response.Write Fact(5)
%>120作用域与 Global
<%
Dim pageLevel
pageLevel = "页面级"
Sub ShowIt()
' 过程内能读页面级变量
Response.Write pageLevel & "<br>"
End Sub
Sub LocalDemo()
Dim pageLevel ' 同名局部变量,遮蔽页面级
pageLevel = "过程级"
Response.Write pageLevel & "<br>"
End Sub
ShowIt
LocalDemo
Response.Write pageLevel & "<br>"
%>页面级
过程级
页面级Sub 里 Dim 一个与页面级同名的变量会遮蔽它,但不会报错。这类「看起来改了其实没改」的问题,靠 Option Explicit 也防不住,只能靠命名区分(如页面级用 g_ 前缀)。