7.1.1 语法或“编译”错误 当我们第一次运行新编写的程序代码时,通常看到的第一种错误类型是“syntax error”。这就是所说的,程序代码上的语法错误。这就像在写作中使用了错误的语法,使读者不能了解其中的含义。而解释器(诸如脚本引擎)和编译器对语法要求得更加严格和准确。 语法错误通常也是最早出现和需要排除的。大多数情况下,解释器和编译器会指出行号和所在行中的字符位置,以及在相应的位置上缺少的内容。下面举一个简单的例子,如下所示的这样一段程序: <% Response.Write "The repayments for your loan are $" & chrPayment _ & " per " & strInterval & , due on the " &strDay & " of each " & strInterval & "." %> 我们希望得到下面的结果: The repayments for your loan are $124.50 per month, due on the 12th of each month. 实际上得到的结果如图7-1所示:
If objASPError.ASPDescription > "" Then Response.Write Server.HTMLEncode(objASPError.ASPDescription) & "<br>"
blnErrorWritten = False
Response.Write "<B>"
If objASPError.Description > "" Then Response.Write Server.HTMLEncode(objASPError.Description) & "<br>"
' Only show the Source if it is available and the request is from the same machine as IIS … 文件中第3行是Response.Write语句的第2行。报告错误信息时,VBScript解释器忽略一行中的引导空格和制表符。所以在数完26个字符之后,可以找到语法错误的地方,这里明显缺少了一个双引号。加上双引号后再运行这个页面,我们可以得到如图7-2所示:
图7-2 程序执行结果2 这次又是另外一个简单错误。实际上错误出现在第3行而不是第4行。我们漏掉了第三行末尾的续行符'_'。程序代码应该是: <% Response.Write "The repayments for your loan are $" & chrPayment _ & " per " & strInterval & ", due on the " &strDay & " of each " _ & strInterval & "." %> 1. 错误出现在什么地方 需要注意的是脚本解释器仅指出所发现错误的地方,但实际上那儿并不一定是错误真正出现的地方。在上例中,前面三行的语法正确的;并产生相应的输出结果,而恰恰是第4行引起问题,因为这一行是以一种非法字符开头的,脚本解释器没有意识到这一行是上一行的一部分。 这样的错误是普遍存在的,因为通常我们主要考虑的是要输出的文本内容,而不是双引号、连字符(在VBScript中为“&”)、续行符等的正确顺序。 对于关键字、内部函数名拼写错误或函数的非法参数列表而引起的语法错误,通常比较容易发现,因为错误信息提示可能就指出了错误的实际位置。例如:下面这段代码是想把明天的日期写入页面。 Response.Write DateAdd(Now(),"d", 1) 实际得到的结果如图7-3所示:
图7-3 程序执行结果3 这是因为DateAdd函数的语法应该是: DateAdd (interval_string, interval_number, start_date) 所以应该改写为如下的代码: Response.Write DateAdd("d", 1, Now()) 脚本解释器检测到了我们为第二个参数提供的是一个字符型数据,而DateAdd函数需要的是整型数据类型。 代码结构和脚本结构 语法错误的另一个原因是:当制作网页时使用嵌套的或复杂的脚本结构,如If Then … Else … End If或者Do While … Loop。这有时会造成难以找到的语法错误。 例如下面这段程序: <% If Len(Request.Form("cmdSet")) Then strCounterName = Request.Form("lstSet") strNewValue = Request.Form("txtSet") If IsNumeric(strNewValue) Then intNewValue = Cint(strNewValue) objCounters.Set strCounterName, intNewValue Response.Write "Set counter " & strCounterName & " to " & strNewValue Else Response.Write strNewValue & " is not a valid number" If Len(Request.Form("cmdRemove")) Then strCounterName = Request.Form("lstRemove") objCounters.Remove strCounterName Response.Write "Removed counter " & strCounterName End If End If %> 产生的错误如图7-4所示:
图7-4 程序执行结果4 为什么提示在网页程序中需要一个End语句呢?看一下程序就可以发现,丢失了一个End If,而不是End,在程序的最末尾应该还有另一个End If。 … Response.Write "Removed counter " & strCounterName End If End If End If %> 在这种情况下,根据代码的缩排格式可以很容易地找到相应的错误。特别当错误信息指出错误的大致位置时,很快就可以找到错误位置。然而,这段代码很短,如果在分界符<%…%>中另外还有40行代码,那么错误行号仍然可能指向最后一行(line 56);并且如果在新的代码中的其他脚本结构搞乱了嵌套的结构,错误可能会指向另一个位置。 2. 关于JScript 如果你不是一位javaScript高手,并且确实想试验一些语法错误,那么就从VBScript切换到JScript。JScript比VBScript对程序编写的要求更严格,并且对关键字和变量名大小写敏感,看下面的程序段。 <% var datToday = new Date(); Response.Write(datToday.GetMonth()); %> 运行这段程序会产生“Object doesn’t support this PRoperty or method”(对象不支持这种属性或方法)错误,如图7-5所示:
图7-5 程序执行结果5 原因很简单,返回月份数的JScript函数是getMonth,而不是GetMonth。下面这段程序就可以正常运行。 <% var datToday = new Date(); Response.Write(datToday.getMonth()); %> 当然,如果重试这段程序,可能得不到同样的错误消息。我们第一次运行这段程序时,得到如图7-6所示的错误。