JavaScript 在错误处理调试上一直是它的软肋,若是脚本出错,给出的提示常常也让人摸不着头脑。javascript
ECMAScript 第 3 版为了解决这个问题引入了 try...catch 和 throw 语句以及一些错误类型,让开发人员更加适时的处理错误。java
一.浏览器错误报告web
随着浏览器的不断升级,JavaScript 代码的调试能力也逐渐变强。IE、Firefox、Safari、Chrome 和 Opera 等浏览器,都具有报告 JavaScript错误的机制。只不过,浏览器通常面向的是普通用户,默认状况下会隐藏此类信息。数组
IE:在默认状况下,左下角会出现错误报告,双击这个图标,能够看到错误消息对话框。若是开启禁止脚本调试,那么出错的时候,会弹出错误调试框。设置方法为:工具->InternetOptions 选项->高级->禁用脚本调试,取消勾选便可。浏览器
Firefox:在默认状况下,错误不会经过浏览器给出提示。但在后台的错误控制台能够查看。查看方法为:工具->[Web 开发者]->Web 控制台|错误控制台。除了浏览器自带的,开发人员为 Firefox 提供了一个强大的插件:Firebug。它不但能够提示错误,还能够调试 JavaScript和 CSS、DOM、网络连接错误等。服务器
Safari:在默认状况下,错误不会经过浏览器给出提示。因此,咱们须要开启它。查看方法为:显示菜单栏->编辑->偏好设置->高级->在菜单栏中显示开发->显示 Web 检查器|显示错误控制器。网络
Opera:在默认状况下,错误会被隐藏起来。打开错误记录的方式为:显示菜单栏->查看->开发者工具->错误控制台。app
Chrome:在默认状况下,错误会被隐藏起来。打开错误记录的方法为:工具->JavaScript控制台。函数
二.错误处理工具
良好的错误处理机制能够及时的提醒用户,知道发生了什么事,而不会惶恐不安。为此,做为开发人员,咱们必须理解在处理 JavaScript错误的时候,都有哪些手段和工具能够利用。
try-catch 语句
ECMA262 第 3 版引入了 try-catch 语句,做为 JavaScript 中处理异常的一种标准方式。
try {//尝试着执行 try 包含的代码 window.abcdefg();//不存在的方法 } catch (e) {//若是有错误,执行 catch,e 是异常对象 alert('发生错误啦,错误信息为:' + e);//直接打印调用 toString()方法 }
在 e 对象中,ECMA-262 还规定了两个属性:message 和 name,分别打印出信息和名称。
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.stack); } 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: invalid array length(无效的数组的长度)
PS:RangeError 错误通常在数值超出相应范围时触发
错误信息为:ReferenceError: a is not defined(a 是没有定义的)
PS:ReferenceError 一般访问不存在的变量产生这种错误
错误信息为:SyntaxError: missing ; before statement(失踪;语句以前)
PS:SyntaxError 一般是语法错误致使的
错误信息为:TypeError: 10 is not a constructor(10 不是一个构造函数)
PS:TypeError 一般是类型不匹配致使的
PS:EvalError 类型表示全局函数 eval()的使用方式与定义的不一样时抛出,但实际上并不能产生这个错误,因此实际上碰到的可能性不大。
PS:在使用 encodeURI()和 decodeURI()时,若是 URI 格式不正确时,会致使 URIError错误。但由于 URI 的兼容性很是强,致使这种错误几乎见不到。
利用不一样的错误类型,能够更加恰当的给出错误信息或处理。
[task]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 }
PS:常规错误和这种浏览器兼容错误,咱们都不建议使用 try-catch。由于常规错误能够修改代码便可解决,浏览器兼容错误,能够经过普通 if 判断便可。而且 try-catch 比通常语句消耗资源更多,负担更大。因此,在万不得已,没法修改代码,不能经过普通判断的状况下才去使用 try-catch,好比后面的 Ajax 技术。
抛出错误
使用 catch 来处理错误信息,若是处理不了,咱们就把它抛出丢掉。抛出错误,其实就是在浏览器显示一个错误信息,只不过,错误信息能够自定义,更加精确和具体。
try { new 10; } catch (e) { if (e instanceof TypeError) { throw new TypeError('实例化的类型致使错误!'); //直接中文解释错误信息 } else { throw new Error('抛出未知错误!'); } }
PS:IE 浏览器只支持 Error 抛出的错误,其余错误类型不支持。
三.错误事件
error 事件是当某个 DOM 对象产生错误的时候触发。
addEvent(window, 'error', function () { alert('发生错误啦!') }); new 10;//写在后面 <img src="123.jpg" onerror="alert('图像加载错误!')" />
四.错误处理策略
因为 JavaScript 错误均可能致使网页没法使用,因此什么时候搞清楚及为何发生错误相当重要。这样,咱们才能对此采起正确的应对方案。
常见的错误类型
由于 JavaScript 是松散弱类型语言,不少错误的产生是在运行期间的。通常来讲,须要关注 3 种错误:
1.类型转换错误;2.数据类型错误;3.通讯错误,这三种错误通常会在特定的模式下或者没有对值进行充分检查的状况下发生。
4.1 类型转换错误
在一些判断比较的时候,好比数组比较,有相等和全等两种:
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 是弱类型语言,在使用变量和传递参数以前,不会对它们进行比较来确保数据类型的正确。因此,这样开发人员必须须要靠本身去检测。
function getQueryString(url) {//传递了非字符串,致使错误 var pos = url.indexOf('?'); return pos; } alert(getQueryString(1));
PS:为了不这种错误的出现,咱们应该使用类型比较。
function getQueryString(url) { if (typeof url == 'string') {//判断了指定类型,就不会出错了 var pos = url.indexOf('?'); return pos; } } alert(getQueryString(1));
对于传递参数除了限制数字、字符串以外,咱们对数组也要进行限制。
function sortArray(arr) { if (arr) {//只判断布尔值远远不够 alert(arr.sort()); } } var box = [3,5,1]; sortArray(box);
PS:只用 if (arr)判断布尔值,那么数值、字符串、对象等都会自动转换为 true,而这些类型调用 sort()方法好比会产生错误,这里提一下:空数组会自动转换为 true 而非 false。
function sortArray(arr) { if (typeof arr.sort == 'function') {//判断传递过来 arr 是否有 sort 方法 alert(arr.sort());//就算这个绕过去了 alert(arr.reverse());//这个就又绕不过去了 } } var box = {//建立一个自定义对象,添加 sort 方法 sort : function () {} }; sortArray(box);
PS:这断代码本意是判断 arr 是否有 sort 方法,由于只有数组有 sort 方法,从而判断 arr是数组。但忘记了,自定义对象添加了 sort 方法就能够绕过这个判断,且 arr 还不是数组。
function sortArray(arr) { if (arr instanceof Array) { alert(arr.sort()); } } var box = [3,5,1]; sortArray(box);
通讯错误
在使用 url 进行参数传递时,常常会传递一些中文名的参数或 URL地址,在后台处理时会发生转换乱码或错误,由于不一样的浏览器对传递的参数解释是不一样的,因此有必要使用编码进行统一传递。
好比:?user=李炎恢&age=100
PS:在 AJAX 章节中咱们会继续探讨通讯错误和编码问题。
五.调试技术
在 JavaScript 初期,浏览器并无针对 JavaScript 提供调试工具,因此开发人员就想出了一套本身的调试方法,好比 alert()。这个方法能够打印你怀疑的是否获得相应的值,或者放在程序的某处来看看是否能执行,得知以前的代码无误。
//使用 instanceof 判断是 Array 最为合适 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 对象的方法
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 的话,全部要调试的变量一目了然,也不须要删除,放着也没事。
将错误抛出
以前已经将结果错误的抛出,这里不在赘述。
六.调试工具
IE八、Firefox、Chrome、Opera、Safari 都自带了本身的调试工具,而开发人员只习惯了Firefox 一种,因此不少状况下, Firefox 开发调试,在而后去其余浏览器作兼容。其实 Firebug工具提供了一种 Web 版的调试工具: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');
还有一种离线版,把 firebug-lite 下载好,载入工具便可,致使最终工具没法运行,其余浏览器运行无缺。虽然 Web 版本的 Firebug Lite 能够跨浏览器使用 Firebug,但除了 Firefox原生的以外,都不支持断点、单步调试、监视、控制台等功能。好在,其余浏览器本身的调试器都有。
PS:Chrome 浏览器必须在服务器端方可有效。测试也发现,只能简单调试,若是遇到错误,系统不能自动抛出错误给 firebug-lite。
1.设置断点
咱们能够选择 Script(脚本),点击要设置断点的 JS脚本处,便可设置断点。当咱们须要调试的时候,从断点初开始模拟运行,发现代码执行的流程和变化。
2.单步调试
设置完断点后,能够点击单步调试,一步步看代码执行的步骤和流程。上面有五个按钮:
从新运行:从新单步调试
断继:正常执行代码
单步进入:一步一步执行流程
单步跳过:跳到下一个函数块
单步退出:跳出执行到内部的函数
3.监控
单击“监控”选项卡上,能够查看在单步进入是,全部变量值的变化。你也能够新建监
控表达式来重点查看本身所关心的变量。
4.控制台
显示各类信息。以前已了解过。
PS:其余浏览器除 IE8 以上都可实现以上的调试功能,你们能够本身常识下。而咱们主要采用 Firebug进行调试而后兼容到其余浏览器的作法以提升开发效率。
http://websqq.org/archives/1487