JavaScript错误处理与调试javascript
学习要点:java
1.浏览器错误报告数组
2.错误处理浏览器
3.错误事件服务器
4.错误处理策略网络
5.调试技术app
6.调试工具函数
JavaScript在错误处理调试上一直是它的软肋,若是脚本出错,给出的提示常常也让人摸不着头脑。ECMAScript第3版为了解决这个问题引入了try...catch和throw语句以及一些错误类型,让开发人员更加适时的处理错误。工具
一.浏览器错误报告学习
随着浏览器的不断升级,JavaScript代码的调试能力也逐渐变强。IE、Firefox、Safari、Chrome和Opera等浏览器,都具有报告JavaScript错误的机制。只不过,浏览器通常面向的是普通用户,默认状况下会隐藏此类信息。
IE:在默认状况下,左下角会出现错误报告,双击这个图标,能够看到错误消息对话框。若是开启禁止脚本调试,那么出错的时候,会弹出错误调试框。设置方法为:工具->Internet Options选项->高级->禁用脚本调试,取消勾选便可。
Firefox:在默认状况下,错误不会经过浏览器给出提示。但在后台的错误控制台能够查看。查看方法为:工具->[Web开发者]->Web控制台|错误控制台。除了浏览器自带的,开发人员为Firefox提供了一个强大的插件:Firebug。它不但能够提示错误,还能够调试JavaScript和CSS、DOM、网络连接错误等。
Safari:在默认状况下,错误不会经过浏览器给出提示。因此,咱们须要开启它。查看方法为:显示菜单栏->编辑->偏好设置->高级->在菜单栏中显示开发->显示Web检查器|显示错误控制器。
Opera:在默认状况下,错误会被隐藏起来。打开错误记录的方式为:显示菜单栏->查看->开发者工具->错误控制台。
Chrome:在默认状况下,错误会被隐藏起来。打开错误记录的方法为:工具->JavaScript控制台。
二.错误处理
良好的错误处理机制能够及时的提醒用户,知道发生了什么事,而不会惶恐不安。为此,做为开发人员,咱们必须理解在处理JavaScript错误的时候,都有哪些手段和工具能够利用。
try-catch语句
ECMA262第3版引入了try-catch语句,做为JavaScript中处理异常的一种标准方式。
try尝试着执行try包含的代码
catch若是有错误,执行catch,能够接收一个参数e,e是异常对象包含异常错误信息
try { //尝试着执行try包含的代码 window.abcdefg(); //不存在的方法 } catch (e) { //若是有错误,执行catch,e是异常对象 alert('发生错误啦,错误信息为:' + e); //直接打印调用toString()方法 }
ps:尝试执行try里面的代码,若是出现错误,就执行catch里面的代码,catch()接收一个参数e里面包含错误信息
try-catch特色
1.能够获取错误信息
2.能够避免浏览器控制台报错
3.能够屏蔽错误,继续执行,可是继续执行的语句若是和错误的语句有上下文关联,那么下面可能会继续出错
catch(e)接收的e错误信息对象里,有两个属性message和name,分别打印出信息和名称。
message错误信息,【推荐使用】通常使用这个就够了,并且跨浏览器支持
name错误名称,IE9如下不支持name属性
使用方式:
catch(e)接收的e错误信息对象里.message
catch(e)接收的e错误信息对象里.name
try { //尝试着执行try包含的代码 window.abcdefg(); //不存在的方法 } catch (e) { //若是有错误,执行catch,e是异常对象 alert(e.name ); //打印错误名称 alert(e.message)//打印错误信息 }
PS:Opera9以前的版本不支持这个属性。而且IE提供了和message彻底相同的description属性、还添加了number属性提示内部错误数量。Firefox提供了fileName(文件名)、lineNumber(错误行号)和stack(栈跟踪信息)。Safari添加了line(行号)、sourceId(内部错误代码)和sourceURL(内部错误URL)。因此,要跨浏览器使用,那么最好只使用通用的message。
finally子句
finally语句做为try-catch的可选语句,无论是否发生异常处理,都会执行。而且无论try或是catch里包含return语句,也不会阻止finally执行。
try { //尝试执行里面的代码 window.abcdefg(); } catch (e) { //若是发生错误就执行里面的代码 alert('发生错误啦,错误信息为:' + e); } finally { //无论是否发生错误都执行里面代码 alert('我都会执行!'); }
PS:finally的做用通常是为了防止出现异常后,没法往下再执行的备用。也就是说,若是有一些清理操做,那么出现异常后,就执行不到清理操做,那么能够把这些清理操做放到finally里便可。
错误类型
执行代码时可能会发生的错误有不少种。每种错误都有对应的错误类型,ECMA-262定义了7种错误类型:
1.Error
2.EvalError
3.RangeError
4.ReferenceError
5.SyntaxError
6.TypeError
7.URIError
其中,Error是基类型(其余六种类型的父类型),其余类型继承自它。Error类型不多见,通常由浏览器抛出的。这个基类型主要用于开发人员抛出自定义错误。
PS:抛出的意思,就是当前错误没法处理,丢给另一我的,好比丢给一个错误对象。如当代码出现错误时,浏览器没法处理错误,就在控制台抛出一个错误信息
RangeError(范围错误)
错误信息为:RangeError: invalid array length(无效的数组的长度)
PS:RangeError错误通常在数值超出相应范围时触发
new Array(-5); //抛出RangeError(范围)
ReferenceError(引用错误)
错误信息为:ReferenceError: a is not defined(a是没有定义的)
PS:ReferenceError一般访问不存在的变量产生这种错误
var box = a; //抛出ReferenceError(引用)
SyntaxError(语法错误)
错误信息为:SyntaxError: missing ; before statement(失踪;语句以前)
PS:SyntaxError一般是语法错误致使的
a $ b; //抛出SyntaxError(语法)
TypeError(类型错误)
错误信息为:TypeError: 10 is not a constructor(10不是一个构造函数)
PS:TypeError一般是类型不匹配致使的
new 10; //抛出TypeError(类型 )
EvalError
PS:EvalError类型表示全局函数eval()的使用方式与定义的不一样时抛出,但实际上并不能产生这个错误,因此实际上碰到的可能性不大。
URIError错误。
PS:在使用encodeURI()和decodeURI()时,若是URI格式不正确时,会致使URIError错误。但由于URI的兼容性很是强,致使这种错误几乎见不到。
利用不一样的错误类型,能够更加恰当的给出错误信息或处理。
try { new 10; } catch (e) { if (e instanceof TypeError) { //若是是类型错误,那就执行这里 alert('发生了类型错误,错误信息为:' + e.message); } else { alert('发生了未知错误!'); } }
善用try-catch
在明明知道某个地方会产生错误,能够经过修改代码来解决的地方,是不适合用try-catch的。或者是那种不一样浏览器兼容性错误致使错误的也不太适合,由于能够经过判断浏览器或者判断这款浏览器是否存在此属性和方法来解决。
try { var box = document.getElementbyid('box'); //单词大小写错误,致使类型错误 } catch (e) { //这种状况不必try-catch alert(e); }
try { alert(innerWidth); //W3C支持,IE报错 } catch (e) { alert(document.documentElement.clientWidth); //兼容IE }
以上两种状况都不适合用try-catch
PS:常规错误和这种浏览器兼容错误,咱们都不建议使用try-catch。由于常规错误能够修改代码便可解决,浏览器兼容错误,能够经过普通if判断便可。而且try-catch比通常语句消耗资源更多,负担更大。因此,在万不得已,没法修改代码,不能经过普通判断的状况下才去使用try-catch,好比后面的Ajax技术。
抛出错误
使用catch来处理错误信息,若是处理不了,咱们就把它抛出丢掉。抛出错误,其实就是在浏览器显示一个错误信息,只不过,错误信息能够自定义,更加精确和具体。
throw实列化一个错误对象,抛出错误
try { new 10; } catch (e) { if (e instanceof TypeError) { //判断若是错误类型是TypeError类型 throw new TypeError('实例化的类型致使错误!'); //实例化一个TypeError错误对象,向浏览器抛出错误 } else { throw new Error('抛出未知错误!'); //不然实例化一个Error错误对象,向浏览器抛出错误 } }
PS:IE浏览器只支持Error抛出的错误,其余错误类型不支持。
三.错误事件
onerror事件是当某个DOM对象产生错误的时候触发。
//添加一个错误事件,当发生错误时激发函数 addEvent(window, 'error', function () { alert('发生错误啦!') }); new 10; //写在后面,写在事件前面就执行不到事件了 //跨浏览器添加事件,添加事件兼容 function addEvent(obj, type, fn) { //添加事件函数,接收3个参数,1事件对象,2事件名称,3事件函数 //判断浏览器若是支持w3c if (obj.addEventListener) { //就用w3c的addEventListener方法添加对象,将事件名称和事件函数传入添加事件 obj.addEventListener(type, fn, false); } else if (obj.attachEvent) { //判断若是浏览器是IE9如下,就用IE的方法attachEvent添加事件 //将事件名称和事件函数传入建立对象 obj.attachEvent('on' + type, fn); } }
在HTML直接使用onerror事件
<img src="123.jpg" onerror="alert('图像加载错误!')" />
四.错误处理策略
因为JavaScript错误均可能致使网页没法使用,因此什么时候搞清楚及为何发生错误相当重要。这样,咱们才能对此采起正确的应对方案。
常见的错误类型
由于JavaScript是松散弱类型语言,不少错误的产生是在运行期间的。通常来讲,须要关注3种错误:
1.类型转换错误;2.数据类型错误;3.通讯错误,这三种错误通常会在特定的模式下或者没有对值进行充分检查的状况下发生。
类型转换错误
在一些判断比较的时候,好比数组比较,有相等和全等两种:
alert(1 == '1'); //true,相等比较的是值,类型不用比较 alert(1 === '1'); //false,全等比较的是值还要比较类型 alert(1 == true); //true,相等转换成布尔值为真相等 alert(1 === true); //false,全等二者类型不同
PS:因为这个特性,咱们建议在这种会类型转换的判断,强烈推荐使用全等,以保证判断的正确性。
var box = 10; //能够试试0 if (box) { //10自动转换为布尔值为true alert(box); }
PS:由于0会自动转换为false,其实0也是数值,也是有值的,不该该认为是false,因此咱们要判断box是否是数值再去打印。
var box = 0; if (typeof box == 'number') { //判断box是number类型便可 alert(box); }
PS:typeof box == 'number'这里也是用的相等,没有用全等呀?缘由是typeof box自己返回的就是类型的字符串,右边也是字符串,那不必验证类型,因此相等就够了。
数据类型错误
因为JavaScript是弱类型语言,在使用变量和传递参数以前,不会对它们进行比较来确保数据类型的正确。因此,这样开发人员必须须要靠本身去检测。
//自定义函数接收一个url function getQueryString(url) { //判断接收到的参数是不是字符串类型 if (typeof url == 'string') { //判断了指定类型,就不会出错了 var pos = url.indexOf('?'); //若是字符串类型,查找字符串中?在字符串中的索引位置 return pos; //返回索引位置 }else { return '数据类型错误'; //若是不是字符串,返回数据类型错误 } } alert(getQueryString(1)); //执行函数
对于传递参数除了限制数字、字符串以外,咱们对数组也要进行限制
//自定义函数,接收一个对象 function sortArray(arr) { if (typeof arr.sort == 'function') { //判断对象里面的sort是不是一个方法,也就是函数 alert(arr.sort()); //就算这个绕过去了 alert(arr.reverse()); //reverse逆向排序数组,这个就又绕不过去了,出错 } } var box = { //建立一个自定义对象,添加sort方法 sort: function () { } }; sortArray(box); //执行函数
PS:这断代码本意是判断arr是否有sort方法,由于只有数组有sort方法,从而判断arr是数组。但忘记了,自定义对象添加了sort方法就能够绕过这个判断,且arr还不是数组。
//自定义函数,接收一个数组 function sortArray(arr) { //判断接收到的是不是数组类型 if (arr instanceof Array) { //使用instanceof判断是Array最为合适 alert(arr.sort()); //若是是数组类型。从小到达排序 } } var box = [3,5,1]; //建立数组 sortArray(box); //执行函数
通讯错误
在使用url进行参数传递时,常常会传递一些中文名的参数或URL地址,在后台处理时会发生转换乱码或错误,由于不一样的浏览器对传递的参数解释是不一样的,因此有必要使用编码进行统一传递。
好比:?user=李炎恢&age=100
var url = '?user=' + encodeURIComponent('李炎恢') + '&age=100'; //编码
PS:在AJAX章节中咱们会继续探讨通讯错误和编码问题。
五.调试技术
在JavaScript初期,浏览器并无针对JavaScript提供调试工具,因此开发人员就想出了一套本身的调试方法,好比alert()。这个方法能够打印你怀疑的是否获得相应的值,或者放在程序的某处来看看是否能执行,得知以前的代码无误。
var num1 = 1; var num2 = b; //在这段先后加上alert('')调试错误 var result = num1 + num2; alert(result); //打印不到,说明上面哪里有错误
PS:使用alert('')来调试错误比较麻烦,重要裁剪和粘贴alert(''),若是遗忘掉没有删掉用于调试的alert('')将特别头疼。因此,咱们如今须要更好的调试方法。
将消息记录到控制台
IE八、Firefox、Opera、Chrome和Safari都有JavaScript控制台,能够用来查看JavaScript错误。对于Firefox,须要安装Firebug,其余浏览器直接使用console对象写入消息便可。
console对象的方法,将数据信息记录到控制台,有4个方法
方法名 |
说明 |
error(message) |
将错误消息记录到控制台 |
info(message) |
将信息性消息记录到控制台 |
log(message) |
将通常消息记录到控制台 |
warn(message) |
将警告消息记录到控制台 |
4个方法均可以接收一个数据类型,来打印数据,不一样的方法用不一样的标识来打印
console.error('错误!'); //红色带叉 console.info('信息!'); //白色带信息号 console.log('日志!'); //白色 console.warn('警告!'); //黄色带感叹号
PS:这里以Firefox为标准,其余浏览器会稍有差别。
var num1 = 1; console.log(typeof num1); //获得num1的类型 var num2 = 'b'; console.log(typeof num2); //获得num2的类型 var result = num1 + num2; alert(result); //结果是1b,匪夷所思
PS:咱们误把num2赋值成字符串了,其实应该是数值,致使最后的结果是1b。那么传统调试就必须使用alert(typeo num1)来看看是否是数值类型,比较麻烦,由于alert()会阻断后面的执行,看过以后还要删,删完估计一下子又忘了,而后又要alert(typeof num1)来加深印象。若是用了console.log的话,全部要调试的变量一目了然,也不须要删除,放着也没事。
将错误抛出
以前已经将结果错误的抛出,这里不在赘述。
var num1 = 1; if (typeof num1 != 'number') throw new Error('变量必须是数值!'); //判断num1不是数值类型,建立一个错误对象 var num2 = 'b'; if (typeof num2 != 'number') throw new Error('变量必须是数值!'); //判断num2不是数值类型,建立一个错误对象 var result = num1 + num2; alert(result);
六.调试工具
IE八、Firefox、Chrome、Opera、Safari都自带了本身的调试工具,而开发人员只习惯了Firefox一种,因此不少状况下,在Firefox开发调试,而后去其余浏览器作兼容。其实Firebug工具提供了一种Web版的调试工具:Firebug lite。
如下是网页版直接调用调试工具的代码:直接复制到浏览器网址便可。要求必须有网络,链接加载网络版Firebug lite调试工具【不推荐】
javascript:(function(F,i,r,e,b,u,g,L,I,T,E){if(F.getElementById(b))return;E=F[i+'NS']&&F.documentElement.namespaceURI;E=E?F[i+'NS'](E,'script'):F[i]('script');E[r]('id',b);E[r]('src',I+g+T);E[r](b,u);(F[e]('head')[0]||F[e]('body')[0]).appendChild(E);E=new%20Image;E[r]('src',I+L);})(document,'createElement','setAttribute','getElementsByTagName','FirebugLite','4','firebug-lite.js','releases/lite/latest/skin/xp/sprite.png','https://getfirebug.com/','#startOpened');
PS:Chrome浏览器必须在服务器端方可有效。测试也发现,只能简单调试,若是遇到错误,系统不能自动抛出错误给firebug-lite。
离线版firebug-lite
还有一种离线版,把firebug-lite下载好,载入工具便可,致使最终工具没法运行,其余浏览器运行无缺。虽然Web版本的Firebug Lite能够跨浏览器使用Firebug,但除了Firefox原生的以外,都不支持断点、单步调试、监视、控制台等功能。好在,其余浏览器本身的调试器都有。
将下载好的firebug-lite文件夹放到工程根目录下,引入js文件,如:
<script type="text/javascript" src="firebug-lite/build/firebug-lite-beta.js" charset="utf-8"></script>
会自动加载工具
调试步骤
1.设置断点
咱们能够选择Script(脚本),点击要设置断点的JS脚本处,便可设置断点。当咱们须要调试的时候,从断点初开始模拟运行,发现代码执行的流程和变化。
2.单步调试
设置完断点后,能够点击单步调试,一步步看代码执行的步骤和流程。上面有五个按钮:
从新运行:从新单步调试
断继:正常执行代码
单步进入:一步一步执行流程
单步跳过:跳到下一个函数块
单步退出:跳出执行到内部的函数
3.监控
单击“监控”选项卡上,能够查看在单步进入是,全部变量值的变化。你也能够新建监控表达式来重点查看本身所关心的变量。
4.控制台
显示各类信息。以前已了解过。
PS:其余浏览器除IE8以上都可实现以上的调试功能,你们能够本身常识下。而咱们主要采用Firebug进行调试而后兼容到其余浏览器的作法以提升开发效率。