一旦你发现一个错误,就能够清除它。不幸的是,发现它们的
出处并不老是很容易 - 你的大部分调试时间只是花在指出错
误的位置。
最可靠的方法之一是在你的代码中加入一些简单的语句打印出
正在发生什么。假如你在下面的两段程序中发现一个问题:
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助手”。通往神秘真知
的路就在你的脚下 安全