2020-9-8日:错误处理与调试
- try-catch语句 ;
基本语法:
try{ // 可能会导致错误的代码 } catch(error){ // 在错误发生时怎么处理 }
try { window.someNonexistentFunction(); } catch (error){ alert(error.message); // 错误对象的 message 属性; }
- try-catch语句 的finally子句 ;
无论 try 或 catch 语句块中包 含什么代码——甚至 return 语句,都不会阻止 finally 子句的执行;
- try-catch 语句的每一部分都放了一条 return 语句;
- 表面上看,调用这个函数会返 回 2,因为返回 2的 return 语句位于 try 语句块中,而执行该语句又不会出错;
- 由于后还有 一个 finally 子句,结果就会导致该 return 语句被忽略;
- 函数只能返回 0;
- 只要代码中包含 finally 子句,那么无论 try 还是 catch 语句块 中的 return 语句都将被忽略;
function testFinally(){ try { return 2; } catch (error){ return 1; } finally { return 0; } }
- 不同的错误类型;
Error :是基类型,其他错误类型都继承自该类型;
EvalError: 没有把 eval()当成函数调用,就会抛出错误;
RangeError
ReferenceError
SyntaxError
TypeError
URIError
使用 instanceof 操作符:判断错误的类型;
try { someFunction(); } catch (error){ if (error instanceof TypeError){ /处理类型错误 } else if (error instanceof ReferenceError){ //处理引用错误 } else { //处理其他类型的错误 } }
建议:
假设你在使用一个大型 JavaScript 库中的 函数,该函数可能会有意无意地抛出一些错误。由于我们不能修改这个库的源代码,所以大可将对该函 数的调用放在 try-catch 语句当中,万一有什么错误发生,也好恰当地处理它们;
- throw 操作符:随时抛出自定义错误 ;
作用:随时抛出自定义错误;
要求:必须 要给 throw 操作符指定一个值,这个值是什么类型,没有要求
throw 12345; throw "Hello world!"; throw true; throw { name: "JavaScript"};
遇到 throw 操作符时,代码会立即停止执行。仅当有 try-catch 语句捕获到被抛出的值时,代 码才会继续执行;
例子:
自执行函数:
(function myFunction() { try { var x = 120; if (x == "") throw "empty"; if (x > 10) throw "too high"; // x= 120; 抛出异常错误:too high; if (x < 5) throw "too low"; } catch (err) { console.log(err) //catch()捕捉错误,返回值err为抛出的自定义异常错‘ too high’
} })();
- 使用某种内置错误类型,可以更真实地模拟浏览器错误 ;
代码抛出了一个通用错误,带有一条自定义错误消息。
throw new Error("Something bad happened."); // 每种错误类型的构造函数接收一个参 数,即实际的错误消息 --"Something bad happened.";
- 利用原型链:继承 Error 来创建自定义错误类型;
简例:
function CustomError(message){ this.name = "CustomError"; this.message = message; } CustomError.prototype = new Error(); throw new CustomError("My message");
浏览器对待继承自 Error 的自定义错误类型,就像对待其他错误类型一样;
IE:只有在抛出 Error 对象的时候才会显示自定义错误消息。对于其他类型,它 都无一例外地显示"exception thrown and not caught"(抛出了异常,且未被 捕获);
- 抛出错误的时机 ;针对函数为什么会执行失败给出更多信息,抛出自定义错误是一种很方便的方式;
简例:
values 参数不是数组,就会抛出一个错误;错误消息中包含了函数 的名称,以及为什么会发生错误的明确描述
function process(values) { if (!(values instanceof Array)) { throw new Error("process(): Argument must be an array."); } values.sort(); for (var i = 0, len = values.length; i < len; i++) { if (values[i] > 100) { return values[i]; } } return -1; }
- window 对象的 error 事件;
- 任何没有通过 try-catch 处理的错误都会触发 ;
- 指定 onerror 事件处理程序,必须使用如下所示的 DOM0级技术,它没有遵循“DOM2级 事件”的标准格式;
-
window.onerror = function(message, url, line){ alert(message); };
- 返回 false,可以阻止浏览器报告错误的默认行;
window.onerror = function(message, url, line){ // onerror 事件处理程序都不会创建 event 对象, 但它可以接收三个参数:错误消息、错误所在的 URL 和代码行号;一般主要是错误信息有用; alert(message); return false; };
返回 false,这个函数实际上就充当了整个文档中的 try-catch 语句;
图像也支持 error 事件;
src 特性中的 URL不能返回可以被识别的图像格式,就会触 发 error 事件;
var image = new Image(); EventUtil.addHandler(image, "load", function(event){ alert("Image loaded!"); }); EventUtil.addHandler(image, "error", function(event){ alert("Image not loaded!"); }); image.src = "smilex.gif"; //指定不存在的文件
- 加载图像失败时就会显示一个警告框 ;
- 发生 error 事件时,图 像下载过程已经结束,也就是说不能再重新下载了 ;
- 常见的错误类型
类型转换错误
数据类型错误
通信错误 :
1. 第一种通信错误与格式不正确的 URL 或发送的数据有关; 没有使用 encodeURIComponent()对数据进行编码。
http://www.yourdomain.com/?redir=http://www.someotherdomain.com?a=b&c=d
针对"redir="后面的所有字符串调用 encodeURIComponent()就可以解决这个问题,结果将产生 如下字符串:
http://www.yourdomain.com/?redir=http%3A%2F%2Fwww.someotherdomain.com%3Fa%3Db%26c%3Dd
对于查询字符串,应该记住必须要使用 encodeURIComponent()方法;
定义一个处理查询字符串的函数,
function addQueryStringArg(url, name, value) { if (url.indexOf("?") == -1) { url += "?"; // 传入的 URL不包含问 号,还要给它添加问号; } else { url += "&"; // 否则,就要添加一个和号; } url += encodeURIComponent(name) + "=" + encodeURIComponent(value); return url; }
使用:
var url = "http://www.somedomain.com"; var newUrl = addQueryStringArg(url, "redir", "http://www.someotherdomain.com?a=b&c=d"); alert(newUrl);
另外:服务器响应的数据不正确时,也会发生通信错误;
- 致命错误和非致命错误 ;
例子:
for (var i=0, len=mods.length; i < len; i++){ mods[i].init(); //可能会导致致命错误 }
依次对每个模块调用 init()方法;
问题在于:
任何模块的 init() 方法如果出错,都会导致数组中后续的所有模块无法再进行初始化;
修改:
错误变成非致命; 捕捉错误;
for (var i=0, len=mods.length; i < len; i++){ try { mods[i].init(); } catch (ex) { //在这里处理错误 ;例如:跳过当前模块继续初始化等 } }
assert()函数抛出: 自定义的错误; 减少抛出错误所需的代码量,
参数(2个): 一个是求值结果应该为 true 的条件,另一个是条件为 false 时要抛出的错误;
作用: 代替某些函数中需要调试的 if 语句,以便输出错误消息;
定义:
function assert(condition, message) { if (!condition) { throw new Error(message); } }
使用:
function divide(num1, num2) { assert(typeof num1 == "number" && typeof num2 == "number", "divide(): Both arguments must be numbers."); return num1 / num2; }

浙公网安备 33010602011771号