Javascript的错误主要是语法错误和运行时的错误,前者在代码解析时就会出错,影响程序的运行。后者称为异常,影响它所运行的线程。下面就Javascript常见错误进行分析

1.常见的错误和异常

i.拼写错误

任何开发者在编写javascript程序时都犯过拼写错误,例如将document.getElementsByTagName()写成document.getElementByTagName(),将getElementByid()拼写成getElementByID()等。还有一些大小写的问题。例如:

If(photo.href){
var url= photo.href;
}

以上将关键字if拼写成If,导致语法错误,这种拼写错误通常可以通过编写软件高亮显示出来。
而另外一些变量上的错误拼写错误则稍微马轩写,需要开发的人耐心检查,例如:

var PhotoAlbum = "isaac";
var PhotoAlbumWife = "fresheggs";
alert("the photo:\n"+
PhotoAbulm + "and" + PhotoAlbumWife);

会提示 PhotoAbulm is not defined(变量未定义。)通过检查我们发现,定义了“PhotoAlbum”而未定义PhotoAbulm。

ii.访问未存在的变量。

最规范的变量定义都是通过var,但是javascript允许不使用关键字而直接定义变量。比如以下代码都是合法的

  var isaac = "husband of fresheggs";
fresheggs = "wife of isaac";

这就无形中给检查代码增加了麻烦,像下面几行代码是比较容易发现的,浏览器也会相应的给出变量不存在的位置。

var isaac = "husband of fresheggs";
alert(fresheggs);
fresheggs = "wife of isaac";

但是很多时候,错误是十分隐蔽的

<script language="javascript">
var oInputField;
var oPopDiv;
var oColorsUl;
var aColors = ["red", "green", "blue", "magenta", "yellow", "cornfloewrblue"]; function clearColors() {
for (var i = oColorsUl.childNodes.length - 1; i >= 0; i--)
oColorsUl.removeChild(oColorsUl.childNodes[i]);
oPopDiv.className = "hide";
} function setColors(the_clors) {
oInputField = document.forms["myForm1"].colors;
oPopDiv = document.getElementById("popup");
oColorsUl = document.getElementById("colors_ul");
clearColors();
oPopDiv.className = "show";
var oLi;
for (var i = 0; i < aColors.length; i++) {
oLi = document.createElement("li");
oColorsUl.appendChild(oLi);
oLi.appendChild(document.createTextNode(the_colors[i])); oLi.onmouseover = function() {
this.className = "mouseOver";
}
oLi.onmouseout = function() {
this.className = "mouseOut";
}
oLi.onclick = function() {
oInputField.value = this.firstChild.nodeValue;
clearColors();
}
}
}
</script>
<form method="post" name="myForm1">
Color:
<input type="text" name="colors" id="colors" onkeyup="setColors(aColors);" />
</form>
<div id="popup">
<ul id="colors_ul"></ul>
</div>

浏览器告知:Uncaught ReferenceError: the_colors is not defined the_colors变量未定义,仔细检查32行

oLi.appendChild(document.createTextNode(the_colors[i]));

确没有错误,其实错误在第22行拼写错误。这样提示和错误不符大大增加了检查的难度。

function setColors(the_clors) 

iii.括号不匹配

编写较长的逻辑关系代码时,常常需要反复的使用花括弧和小括弧,很多时候因为删除某些代码导致括号和括号后的个数不匹配。

function testPic(x, start, end) {
if (x <= end && x >= start) {
if (x == start) {
alert(x + " is the start of the range");
}
if (x == end) {
alert(x + " is the end of the range");
}
if (x != start && x != end) {
alert(x + " is in the range");
} else {
alert(x + " is not in the range");
}
}
testPic(7, 5, 8);

错误报告10行缺少},但行数不一定在10行。

正确代码

function testPic(x, start, end) {
if (x <= end && x >= start) {
if (x == start) {
alert(x + " is the start of the range");
}
if (x == end) {
alert(x + " is the end of the range");
}
if (x != start && x != end) {
alert(x + " is in the range");
}
} else {
alert(x + " is not in the range");
}
}
testPic(7, 5, 8);

从正确的代码可以看到,要避免括号遗漏的最有效办法是养成规范的编码习惯,适当应用tab 空行等

iiii.字符串和变量连接错误

javascript在输出结果时常常需要将字符串和变量连接,因此加号和引号都很多,容易错漏

father = "isaac";
mother = "fresheggs";
child = "none";
family = father+" "+mother+" "child;

如上面的代码,在child前边漏掉了+号,导致程序错误

还有一种典型的连接错误就是javascript的类型转化。如下代码

a = 10;
b = 20;
c = 30;
alert("a+b+c="+a+b+c);

执行结果102030显然不是我们所想要的结果,解决上述问题的办法就是利用括号把数值部分和文字串部门分别做处理,然后加起来。

a = 10;
b = 20;
c = 30;
alert("a+b+c="+(a+b+c));

iiiii.等号与赋值混淆。

在条件判断中,常常会把等号==误写成赋值符号= ,这样的语法没有任何问题,javascript会把它处理成赋值是否成功来判断真假

if (isaac = "talking"){
fresheggs.hear();
}

以上代码的执行结果是将变量isaac赋值为"talking",如果赋值成功,则执行花括弧中的fresheggs,但开发者的本意是

if (isaac == "talking"){
fresheggs.hear();
}

即当isaac的变量值为"talking"时,执行fresheggs.hear();这样的问题在程序检查中是很难发现的

2.错误处理

i.用alert()和document.write()来监视变量值

在日常开发中,alert()和document.write()来监视变量值,恐怕是最常用和有些的解决的方法。

alert()在开发中会跳出目前的变量值,并中止程序的运行,直到点击确定后继续执行。document.write()方法则是输出变量值后继续执行程序,因为两者的执行方法不同,所以给开发者带来了选择上的技巧。

for(var i=0;i<aColors.length;i++)
if(aColors[i].indexOf(oInputField.value)==0)
aResult.push(aColors[i]);

为了检测传入aResult的值,常给if加入alert()方法来检测,如果值很多,最好使用document.write()方法来检测传入值,避免反复的进行确定

ii.使用onerro方法

当页面出现错误时,onerro事件使用window对象触发,告诉开发者哪出了错误。

<script language="javascript">
window.onerror = function(){
alert("出错啦!");
}
</script>
</head>
<body onload="nonExistent()">
</body>

利用window.onload引用一个不存在的函数引发异常,浏览器本身也出现了调试错误,要屏蔽错误信息,只需要在onerror函数后面加return true即可。

    <script type="text/javascript">
window.onerror = function(){
alert("出错啦!");
return true; //屏蔽系统事件
}
</script>
</head>
<body onload="nonExistent()">
</body>

但是这样对处理错误没有任何帮助,其实onerror提供了三个参数确定错误性质

<script type="text/javascript">
window.onerror = function(sMessage,sUrl,sLine){
alert("出错了:\n"+sMessage+"\n 地址:"+ sUrl +"\n行号:"+sLine);
return true; //屏蔽系统事件
}
</script>

iii.使用try...catch语句找到错误

js中借鉴了java的try...catch方法,该语句会先运行try里边的方法,如果出现错误则跳转运行catch()里面的代码,如果有finnally,则无论是否错误都运行其后的代码

try...catch的语法如下:

try...catch的代码语法如下:
try{
//代码
}catch([exception]){
//如果try里面的代码有错,则运行
}[finally{
//最后运行,无论是否出错
}]

例子:使用try...catch语法找错误

<script type="text/javascript">
try{
alert("this is an example");
alert(fresheggs);
} catch(exception){
var sError = "";
for(var i in exception)
sError += i + ":" + exception[i] + "\n";
alert(sError);
}
</script>

在以上语法中特意输出一个未定义的变量fresheggs,导致了异常,由此运行catch里面的代码,此时浏览器会跳出错误

通过try...catch能轻松的找到错误,但可惜的是该语句并不能很好的处理语法错误。

如下:try语句中出现了语法错误,而这个代码并没有运行catch中的代码。

<script type="text/javascript">
try{
alert("this is an example") );
} catch(exception){
var sError = "";
for(var i in exception)
sError += i + ":" + exception[i] + "\n";
alert(sError);
}
</script>

3.使用调试器

尽管javascript不具有调试功能,但是我们借助ie或者firefox浏览器的控制台或者调试插件能起到调试作用。

i.使用firefox错误控制台进行调试

使用firefox错误控制台,我们在页面中右键鼠标,审查元素,调到控制台,js选项就可以看到浏览器把页面运行的所有js错误信息都传到错误控制台上,单击每条信息就会打开对于的代码。

firefox错误调试平台比ie准确的多,在没有特殊需求的调试要求下,是个不错的选择。

ii.使用Microsoft Script debugger进行调试

http://www.microsoft.com/zh-cn/download/details.aspx?id=23992

iii.使用Venkman

在火狐浏览器中直接安装即可。

关于vankman 请参看http://jiangzhengjun.iteye.com/blog/481500一文。

4.javascript的优化

i.减缓代码的下载时间。
web浏览器下载的是javascript的源码,其中包含的长变量名、注释、空格换行等内容减缓了代码的下载时间。这些字符对于团队编写代码十分有效但在工程上传到服务器时应当删除。
如以下代码

<script type="text/javascript">
function showMeTheMoney(money){
if(!money){
return false;
}else{
...
}
}
</script>

可以优化成

function showMeTheMoney(money){if(!money){return false;}else{...}}

这样优化后节省了20个字符,若这个项目是一个很大的工程,将节省很大的服务器空间,不但提高了下载速度,也减少了服务器的压力。另外对于布尔型的值,true和false,true都可以用1来替换,false可以用0来替换,对于true来说节省了3个字符,对于false来说节省了4个字符,例如

var bSearch = false;
for(var i = 0;i<aChoices.length&&!bSearch;i++){
if(aChoices[i]==vValue)
bSearch=true;
}

替换成

var bSearch = 0;
for(var i = 0;i<aChoices.length&&!bSearch;i++){
if(aChoices[i]==vValue)
bSearch=1;
}

代码的执行效率,结果都相同,但节省了7个字符。

代码中常常会出现检测某个值是否为有效值的语句,而很多条件非的判断就是判断某个变量是否为"undefined"、"null"、"false"

if(myValue !=undefined){
...//
}
if(myValue !=null){
...//
}
if(myValue !=false){
..///
}

尽管这些操作符都正确,但使用“逻辑非”操作符“!”也能达到同样的效果。

if(!myValue){
...//
}

而且不影响代码的可读性。类似的替换还有

var myTalk = new Array myTalk();
var myTalk =[];
var myTack = new Array myTack{};
var myTack ={};

另外,在编写代码时为了提高可读性,函数名称,变量名尽量使用简单明了的代码

function AddThreeVarsRogether(first Var,second Var,Third Var){
return(firstVar+secondVar+thirdVar)
}

可以缩写成

function A(a,b,c){return(a+b+c)}

ii.合理声明变量

合理的声明全局变量和局部变量,一个原则,尽量使用局部变量,即用即销。

iii.使用内置函数缩短编译时间

因为尽量的使用内置函数,因为这些函数类似C,Java都是通过编译好的,比起实时编译的javascript效率高很多。

function myPower(iNum, n){
var iResult = iNum;
for(var i=1;i<n;i++)
iResult *= iNum;
return iResult;
}
document.write(myPower(5,3));

例如计算指数,以上的代码逻辑没有问题,但是比内置的函数Math.pow(5,3);执行起来效率低很多

如以下代码

function myPower(iNum, n){
var iResult = iNum;
for(var i=1;i<n;i++)
iResult *= iNum;
return iResult;
}
var myDate1 = new Date();
for(var i=0;i<150000;i++){
myPower(7,8); //自定义方法
}
var myDate2 = new Date();
document.write(myDate2-myDate1);
document.write("<br>");
myDate1 = new Date();
for(var i=0;i<;i++){
Math.pow(7,8); //采用系统内置方法
}
myDate2 = new Date();
document.write(myDate2-myDate1);

让指数函数各运算15万次,然后分别计算运行时间,发现内置方法要比myPower方法快很多。

iiii.合理书写if语句。

if可能是代码中使用频率最多的,然而可惜他的执行效率不高,因此,在多个if else时,尽量把可能性最高的放在第一个,把可能性第二高的放在第二个,以此类推。

    var iNum = 1111;
if(iNum>0&&iNum<){
alert("在0-100之间!")
}else
if(iNum>100&&iNum<){
alert("在100-200之间")
}else
if(iNum>200&&iNum<){
alert("200-300之间")
}else
{alert("小于0或大于300!")}

另外,以上代码还可以优化成

if (iNum > 0) {
if (iNum <) {
alert("在0-100之间");
} else {
if (iNum < 200) {
alert("在100-200之间!");
} else {
if (iNum < 300) {
alert("200-300之间!");
} else {
alert("大于300!");
}
} }
}else{
alert("小于0!")
}

以上代码看上去比较复杂,但考虑了多个因素,执行起来要比原来的代码效率高。

另外 ,在超过两种情况下,最好使用switch语句,经常使用switch代替if语句,可使代码效率执行高10倍。由于case可以适合多种类型,大大提高了执行效率。

iiiii.最小化语句数量

var myNumber = 365;
var myString = "yellows";
var aMyNum = [8,8,4,5,6];
var oData = new Date();

以上代码可以用var一次性定义

var myNumber = 365,myString = "yellows",aMyNum = [8,8,4,5,6],oData = new Date();

同样在很多迭代运算时,也尽可能少的减少代码,代码中的语句越少

例如:

var sCar = aCars[i];
i++;

可以写成

var sCar = aCars[i++]

iiiiii.合理使用DOM

javascript对dom的操作可能是最耗时的操作之一,每次javascript对dom操作都要从新渲染页面一次。有比较明显的时间消耗,尽可能的方法就是不在页面上进行dom操作。

    <ul id="parentUl">
<li> 原li </li>
</ul>
<script type="text/javascript">
function addElementLi(obj) {    
var ul = document.getElementById(obj);  
for (var i = 0; i < 10; i++) {
var li = document.createElement("li");    
li.setAttribute("id", "newli" + i);    
li.innerHTML = "动态添加li";    
ul.appendChild(li); 
}   
}
addElementLi("parentUl");
</script>

(本文结束,欢迎大家点评)

Javascript基础系列之(八)Javascript的调试与优化的更多相关文章

  1. javascript基础系列(入门前须知)

    -----------------------小历史---------------------------- javascript与java是两种语言,他们的创作公司不同,JavaScript当时是借 ...

  2. 【JavaScript基础系列】决定你的人生能走多远的,是基础。

    前言 javaScript门槛非常低,一点语法,一个dom,一个bom就可以使用它开发大部分js应用,再加上现在层出不穷的框架极大的简化抽象了javaScript的使用方式,但是我们始终不能忘记的一点 ...

  3. JavaScript基础系列

    JavaScript基础系列 JavaScript是一种基于对象和事件驱动的客户端脚本语言. JavaScript的注释 // 单行 /**/ 多行注释 JavaScript变量,函数名和操作符都是区 ...

  4. JavaScript基础系列目录(2014.06.01~2014.06.08)

    下列文章,转载请亲注明链接出处,谢谢! 链接地址: http://www.cnblogs.com/ttcc/tag/JavaScript%20%E5%9F%BA%E7%A1%80%E7%9F%A5%E ...

  5. Javascript基础系列之(一)JavaScript语法

    javascript的语法 1.区分大小写 javascript中,变量.函数.运算符都区分大小写. 2.弱类型变量 定义变量只用 "var"关键字 var age = 25; v ...

  6. JavaScript基础系列(变量与类型)

    以下内容将JavaScript简称为JS 打开本文时不管你是零基础的初学者还是其他语言的老兵,我都想说程序语言的基础支撑起了整个网络世界,不把这些基础学透之后稍复杂的内容会让你寸步难行. 现在先给编程 ...

  7. javascript基础学习(八)

    javascript之日期对象 学习要点: 日期对象 将日期对象转换为字符串 将日期对象中的日期和时间转换为字符串 日期对象中的日期 日期对象中的时间 设置日期对象中的日期 设置日期对象中的时间 与毫 ...

  8. JavaScript基础笔记(八)DOM扩展

    DOM扩展 一.选择符API Selectors API是由W3C发起制定的一个标准,致力于让浏览器原生支持CSS查询. 一)querySelector() 在Document和Element类型实例 ...

  9. Javascript基础系列之(二)变量

    javascript 中变量通过var关键字(variable)来声明的. var school = "beijingyizhong" 也可以通过var 关键字给变量多个值. va ...

随机推荐

  1. [分享]一个String工具类,也许你的项目中会用得到

    每次做项目都会遇到字符串的处理,每次都会去写一个StringUtil,完成一些功能. 但其实每次要的功能都差不多: 1.判断类(包括NULL和空串.是否是空白字符串等) 2.默认值 3.去空白(tri ...

  2. c++字符串互相转换

    1.string vs char* //string to char* string str; const char* cch = str.c_str(); ]; strcpy(ch,cch); // ...

  3. 《TCP/IP详解 卷一》读书笔记-----TCP连接建立

    1.在每个TCP报文段中,头部的flag字段里的SYN,FIN,RST,PSH可以多个有效,并没有限定为必须只有一个 2.TCP连接建立过程: 1)客户端发送一个SYN报文段,其中包含了客户端要传送的 ...

  4. 边工作边刷题:70天一遍leetcode: day 80

    Palindrome Permutation I/II 要点: oddCount to increase/decrease count II: chars: 先统计,再得到一半的c,相同的在一起,所以 ...

  5. 第23章 SEH结构化异常处理(2)_编译器对系统SEH机制的封装

    23.2 编译器层面对系统SEH机制的封装 23.2.1 扩展的EXCEPTION_REGISTRATION级相关结构:VC_EXCEPTION_REGISTRATION (1)VC_EXCEPTIO ...

  6. AC日记——阶乘之和 洛谷 P1009(高精度)

    题目描述 用高精度计算出S=1!+2!+3!+…+n!(n≤50) 其中“!”表示阶乘,例如:5!=5*4*3*2*1. 输入输出格式 输入格式: 一个正整数N. 输出格式: 一个正整数S,表示计算结 ...

  7. JMeter学习(二)录制脚本

    ---------------------------------------------------------------------------------------------------- ...

  8. 关于codereview工具与建议

    http://www.ibm.com/developerworks/rational/library/11-proven-practices-for-peer-review/

  9. iOS sha1加密算法

    最近在项目中使用到了网络请求签名认证的方法,于是在网上找关于OC sha1加密的方法,很快找到了一个大众使用的封装好的方法,以下代码便是 首先需要添加头文件 #import<CommonCryp ...

  10. Python高手之路【八】python基础之requests模块

    1.Requests模块说明 Requests 是使用 Apache2 Licensed 许可证的 HTTP 库.用 Python 编写,真正的为人类着想. Python 标准库中的 urllib2  ...