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所示的錯誤。