一旦你發現一個錯誤,就能夠清除它。不幸的是,發現它們的
出處並不老是很容易 - 你的大部分調試時間只是花在指出錯
誤的位置。
最可靠的方法之一是在你的代碼中加入一些簡單的語句打印出
正在發生什麼。假如你在下面的兩段程序中發現一個問題:
function getName()
{
var first_name = prompt("what's your first name?","");
var last_name = prompt("what's your last name?","");
var the_name = first_name + " " + last_name;
}
function theGreeting()
{
var the_name = "";
the_name = getName();
if (the_name == "Dave Thau")
{
alert("Hello, oh greatest one!");
} else {
alert("Ahoy palloi!");
}
}
運行這段程序,看看你是否能發現出了什麼問題(Netscape 3.x
的用戶可能會遇到一些錯誤檢查的問題,這是因爲Netscape 3.x
自己的緣由,如下的Javascript例子與此相同)。若是你在警告
對話框中隨意輸入一些名字,你會獲得問候:「Ahoy palloi!」。
可是,若是你在第一個提示對話框中輸入「Dave」,在第二個中
輸入「Thau」,你應該獲得「Hello,oh greatest one!」這條
信息。然而,你仍是隻獲得「Ahoy palloi!」這條信息。很明顯,
函數中出了錯誤。在這個簡單的例子程序中,你或許只是查看
JavaScript代碼就能發現錯誤。然而,當你的代碼變得愈來愈復
雜時,只靠目測來發現錯誤會變得越發困難。
若是JavaScript沒能捕獲你的錯誤,你也沒有經過查看代碼發現
錯誤,有時打印出變量會對你有所幫助。最簡單的方法是象下面
這樣使用一個alert():
// theGreeting gets a name using getName, then presents
// one or two alert boxes depending on what the name is
//function getName()
{
var first_name = prompt("what's your first name?","");
var last_name = prompt("what's your last name?","");
var the_name = first_name + " " + last_name;
alert("in getName, the_name is: " + the_name);
}
// theGreeting gets a name using getName, then presents
// one of two alert boxes depending on what the name is
// function theGreeting()
{
var the_name = "";
the_name = getName();
alert("after getName, the_name = " + the_name);
if (the_name == "Dave Thau")
{
alert("hello, oh greatest one!");
}else{
alert("ahoy palloi!");
}
}
請注意咱們已經在全部重要的地方加入警告語句。如今試着運行
這段程序。若是你輸入名稱「Dave」和「Thau」,你會注意到第
一個警告顯示「in getName, the_name is: Dave Thau,」,但
是第二個警告顯示「after getName, the_name = undefined,」,
這就告訴你在getName()的最後一行事情變得糟糕起來。不知何
故,the_name只在函數存在前正確,可是theGreeting沒有給變
量the_name正確賦值。當你寫的函數能正確運行,但返回值出現
問題時,你最早要作的就是檢查你是否的確讓其返回了一個值。
很明顯,問題就出在這兒。getName()函數指出了名稱,但沒有
返回它。因此咱們應把語句「return the_name;」加到函數末尾。
把一些警告對話框加入你的代碼中是頗有幫助的。不幸的是,每
隔一行就按一次「OK」也是一種痛苦。
不用警告對話框也能調試代碼。一種選擇是把調試信息寫到窗體
的一個文本區內。另外一種多是把調試信息寫在另外一個窗口上。
這兒有一個把調試信息寫在下面文本區的調試代碼的例子。
使你的調試經歷更溫馨的第三個訣竅是這樣的:建立不一樣的調試
等級,而後設置「調試」變量。下面就是在此頁上運行的
JavaScript代碼: 程序員
多數錯誤只是無聊的語法錯誤。記住關閉那些引號,大括號和
小括號會花費很長時間,不過幸運的是JavaScript自動錯誤檢
測器能捕獲大部分此類錯誤。雖然JavaScript錯誤檢測器隨着
日漸複雜的流覽器而不斷完善,可是一些錯誤仍會溜走。下面
是一些須要留意的常見錯誤:
混淆變量名或函數名
大寫和複數變量和函數名產生的錯誤使人煩惱地經
常出現,有時JavaScript錯誤檢測器不能捕獲它們。
經過創建和堅持使用一種對變量和函數的命名協定,
會大大減小這些麻煩的數量。例如,我所有用小寫
字母定義變量,並用下劃線代替空格 (my_variable,
the_data, an_example_variable),用內置符號表
示函數 (addThreeNumbers(), writeError()等)。
我避免使用任何複數,由於我老是忘記那些變量是
不是複數。
偶然地使用了保留字
一些字不能做爲變量名,由於它們已經被JavaScript
使用。例如,不能定義一個叫「if」的變量,由於
它其實是JavaScript的一部分 - 若是使用「if」,
你會遇到各類麻煩。當你由於使用命名爲「if」的
變量而變得瘋狂時,一個叫作「document」的變量
是很誘人的。不幸的是,「document」是一個
JavaScript對象。另外一個常常遇到的問題是把變量
命名爲「name」(窗體元素有「names」屬性)。把
變量命名爲「name」不會總出問題,只是有時 -
這會更令人迷惑 - 這就是避免使用「name」變量的
緣由。
不幸的是,不一樣的流覽器有不一樣的保留字,因此沒
有辦法知道該回避哪些字。最安全的辦法是避免使
用已經成爲JavaScript一部分的字和HTML使用的字。
若是你由於變量遇到問題,而且不能發現哪兒錯了,
試着把變量改個名字。若是成功了,你或許就避開
了保留字。
記住在邏輯判斷時應該用兩個等號
一些流覽器能捕獲這種錯誤,有些卻不能。這是一
種很是常見的錯誤,可是若是流覽器不能替你指
出來,你就很難發現。下面是一個這種錯誤的例子:
var the_name = prompt("what's your name?", "");
if (the_name = "the monkey")
{
alert("hello monkey!");
} else {
alert("hello stranger.");
}
這段代碼將產生「hello monkey!」警告對話框 -
無論你在提示裏敲的是什麼 - 這不是咱們但願的。
緣由是在if-then語句中只有一個等號,這句話告
訴JavaScript你想讓一件事等於另外一件。假設你在
提示中敲的是「robbie the robot」。最開始,變
量the_name的值是「robbie the robot」,可是隨
後if語句告訴JavaScript你想把the_name設爲
「the monkey.」。因而JavaScript很高興地執行你
的命令,送一個「true」消息給if-then語句,結果
警告對話框每次都出現「hello monkey!」。
這種陰險的錯誤會使你發瘋,因此注意使用兩個
等號。
偶然給變量加上了引號,或忘了給字符串加引號
我不時遇到這個問題。JavaScript區分變量和字符
串的惟一方法是:字符串有引號,變量沒有。下面
有一個明顯的錯誤:
var the_name = 'koko the gorilla';
alert("the_name is very happy");
雖然the_name是一個變量,可是程序還會產生一個
提示「the_name is very happy,」的警告對話框。
這是由於一旦JavaScript看見引號包圍着某些東西
就再也不考慮它,因此當你把the_name放在引號裏,
你就阻止了JavaScript從內存中查找它。
下面是一個不太明顯的此類錯誤的擴展(咱們已經
在第三天的課程裏見過):
function wakeMeIn3()
{
var the_message = "Wake up! Hey! Hey! WAKE UP!!!!";
setTimeout("alert(the_message);", 3000);
}
這裏的問題是你告訴JavaScript三秒後執行alert
(the_message)。可是,三秒後the_message將再也不
存在,由於你已經退出了函數。這個問題能夠這樣
解決:
function wakeMeIn3()
{
var the_message = "Wake up!";
setTimeout("alert('" + the_message+ "');", 3000);
}
把the_message放在引號外面,命令「alert('Wake
up!');」由setTimeout預約好,就能夠獲得你想
要的。
這只是一些可能在你的代碼中做祟的很難調試的
錯誤。一旦發現了它們,就有不一樣的或好或差的方
法來改正錯誤。你很幸運,由於你能從個人經驗和
錯誤中獲益 編程
編好程序的關鍵是程序是寫給人的,不是寫給計算機的。如
果你能明白其餘人或許會閱讀你的JavaScript,你就會寫更
清晰的代碼。代碼越清晰,你就越不容易犯錯誤。機靈的代
碼是可愛的,但就是這種機靈的代碼會產生錯誤。最好的經
驗法則是KISS,即Keep It Simple,Sweetie(保持簡單,可愛)。
另外一個有幫助的技術是在寫代碼以前做註釋。這迫使你在動
手以前先想好。一旦寫好了註釋,你就能夠在其下面寫代碼。
下面是一個用這種方法寫函數的例子:
第一步:寫註釋
//function beSassy()
// beSassy asks for a user's name, chooses a random
// insult and returns an alert box with the user's name and the
// insult.
function beSassy()
{
// first write a list of insults
//
// next get the user's name
//
// then choose a random insult
//
// finally, return the personalized sass
//
}
第二步:填充代碼
//function beSassy()
// beSassy asks for a user's name, chooses a random
// insult and returns an alert box with the user's name and the
// insult.
function beSassy()
{
// first write a list of insults
//
var the_insult_list = new Array;
the_insult_list[0] = "your shoe lace is untied";
the_insult_list[1] = "your mama!";
the_insult_list[2] = "it's hard to be insulting";
// next get the user's name
//
var the_name = prompt("What's your name?", "");
// then choose a random insult
//
var the_number = Math.random() * 5;
var insult_number = parseInt(the_number);
var the_insult = the_insult_list[insult_number];
// finally, return the personalized sass
//
alert("Hey " + the_name + " " + the_insult);
}
這種先寫註釋的策略不只迫使你在寫代碼前思考,並且
使編碼的過程看起來容易些 - 經過把任務分紅小的,
易於編碼的各個部分,你的問題看起來就不太象珠穆朗
瑪峯,而象一羣使人愉悅的起伏的小山。
最後...
總以分號結束你的每一條語句。
雖然並非嚴格必需,你應該養成以分號結束每一條語
句的習慣,這樣能夠避免這行後面再有代碼。忘了加
分號,下一行好的代碼會忽然產生錯誤。
把變量初始化爲「var」,除非你有更好的理由不這樣作。
用「var」把變量局域化能夠減小一個函數與另外一個不相
關函數相混淆的機會。
好了,既然你已經知道了如何編碼,下面就讓咱們學習怎樣使
你的JavaScript快速運行。>> sass
一旦你的JavaScript能運行,你就會想到使其運行得更快。
在講解加速代碼的方法以前,讓我先講講「80/20規則」:
百分之八十的優化是由最初百分之二十的工做所完成的。竭
力實現剩餘百分之二十的速度優化是一種巨大的痛苦,並且
常常致使徹底不能讀和難以管理的代碼。簡言之,若是你的
JavaScript運行得很慢,你能夠用不少簡單的方法來加速它,
可是除非你的代碼確實運行得很慢,我不會對它進行再優化。
下面是一些使你的代碼輕鬆運行的方法。
限制循環內的工做量
程序運行慢的最多見緣由是循環內的重複工做。若是一
條命令只須要執行一次,就沒有必要把它放在循環內。
例如:
var index = 0;
while (index <10)
{
var the_date = new Date();
var the_day = the_date.getDay();
var the_name = prompt("what's the kid's name? " ,"");
alert("On " + the_day + " " + the_name + " is a very special person.");
index++;
}
此程序循環執行10次。每次獲得當天的日期,詢問小孩
的名字,而後打印出「On Monday,so-and-so is a
very special person.」。
可是日期是不會改變的,老是今天。因此沒有必要把前
兩行放在循環中。把它們從循環中拿出來,讓其只執行
一次而不是10次,這樣會節省時間:
var index = 0;
var the_date = new Date();
var the_day = the_date.getDay();
while (index <10)
{
var the_name = prompt("what's the kid's name? " ,"");
alert("On " + the_day + " " + the_name + " is a very special person.");
index++;
}
定製if-then-else語句,按最可能到最不可能的順序
由於if-then-else語句在遇到條件爲真時結束,你能夠
經過把最有可能的條件放到最開始來減小須要判斷的語
句的數量。例如:
var pet = prompt("what kind of pet do you have?", "");
if (pet == "cat")
{
doCatStuff();
} else if (pet == "dog")
{
doDogStuff();
} else if (pet == "bird")
{
doBirdStuff();
} else if (pet == "lizard")
{
doLizardStuff();
}
通常來講,程序中的if子句比從lizard到dog須要執行的
邏輯判斷要少。
最小化重複執行的表達式
若是你發現須要重複計算一個特定的表達式,如
var pi=22/7,只計算一次並把它放在一個全局變量中或
許是個好主意。例如,不象下面程序這樣:
function theArea(radius)
{
var pi = 22/7;
var area = pi * radius * radius;
return area;
}
function theCircumference(radius)
{
var pi = 22/7;
var circumference = 2 * pi * radius;
return circumference;
}
而是這樣作:
var pi = 22/7;
function theArea(radius)
{
var area = pi * radius * radius;
return area;
}
function theCircumference(radius)
{
var circumference = 2 * pi * radius;
return circumference;
}
我知道我在用一個全局變量,我也說過這不是一個好主意。
然而,一些數字,如pi,其值在程序中永遠不會改變,是
此規則的特例。經過只計算pi一次,能夠省去額外的計算。
或許時間上的一些小的節省,累加起來會很管用。
若是你發現代碼運行很慢,你只要注意一些事情。這些都
很明顯,可是當你發現你常常忽略象這樣簡單的優化技巧
時,你會很吃驚。
還有,個人朋友,讓咱們結束今天的課程,這也是整個
JavaScript高級教程的結束。若是你已經進行到這兒,
而且你至少讀過過去五天課程中的一半,那麼你已經看
過不少JavaScript代碼了。實際上,若是你能理解跨越
第一部分和第二部分的10課的大部份內容,你就能夠很
安全地把本身稱爲「JavaScript助手」。通往神祕真知
的路就在你的腳下 安全