JavaScript 高级程序设计(第17章 错误处理与调试)

第17章 错误处理与调试

1. 浏览器报告的错误

2. 错误处理

(1) try-catch语句

try {
    window.someNonexistentFunction();
} catch (error){
    alert(error.message);
}
*finally 子句

只要代码中包含 finally 子句,则无论 try 或 catch 语句块中包
含什么代码——甚至 return 语句,都不会阻止 finally 子句的执行。

*错误类型
  1. Error是基类型,其他错误类型都继承自该类型。
  2. EvalError 类型的错误会在使用 eval()函数而发生异常时被抛出。
  3. RangeError 类型的错误会在数值超出相应范围时触发。
  4. ReferenceError类型找不到对象的情况下抛出。
    5.syntaxError,当我们把语法错误的 JavaScript 字符串传入 eval()函数时,就会导致此类错误。
  5. TypeError 类型在 JavaScript 中会经常用到,在变量中保存着意外的类型时,或者在访问不存在的 方法时,都会导致这种错误。错误的原因虽然多种多样,但归根结底还是由于在执行特定于类型的操作 时,变量的类型并不符合要求所致。
    7.URIError在使用 encodeURI()或 decodeURI(),而 URI 格式不正确时,就会导致 URIError 错误。

(2) 抛出错误

  1. 与 try-catch 语句相配的还有一个throw 操作符,用于随时抛出自定义错误。抛出错误时,必须要给 throw 操作符指定一个值,这个值是什么类型,没有要求。
  2. 在遇到 throw 操作符时,代码会立即停止执行。仅当有 try-catch 语句捕获到被抛出的值时,代 码才会继续执行
throw new SyntaxError("I don’t like your syntax.");
throw new TypeError("What type of variable do you take me for?"); throw new RangeError("Sorry, you just don’t have the range.");
throw new EvalError("That doesn’t evaluate.");
throw new URIError("Uri, is that you?");
throw new ReferenceError("You didn’t cite your references properly.");
  1. 利用原型链还可以通过继承 Error 来创建自定义错误类型
function CustomError(message){
        this.name = "CustomError";
        this.message = message;
}
CustomError.prototype = new Error();
throw new CustomError("My message");

*抛出错误的时机

应该在出现某 种特定的已知错误条件,导致函数无法正常执行时抛出错误。

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;
 }

(3) 错误(error)事件

任何没有通过 try-catch 处理的错误都会触发 window 对象的 error 事件
1.在任何 Web 浏览器中,onerror 事件处理程序都不会创建 event 对象, 但它可以接收三个参数:错误消息、错误所在的 URL 和行号。
2.要指定 onerror 事件处理程序,必须使用如下所示的DOM0 级技术,它没有遵循“DOM2 级 事件”的标准格式。

  1. 在事件处理程序中返回 false,可以阻止浏览器报告错误的默认行为。
window.onerror = function(message, url, line){
    alert(message);
    return false;
};
  1. 图像也支持 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"; //指定不存在的文件

(4) 处理错误的策略

(5) 常见的错误类型

*类型转换错误
  1. 类型转换错误发生在使用某个操作符,或者使用其他可能会自动转换值的数据类型的语言结构时。
    在使用相等(==)和不相等(!=)操作符,或者在 if、for 及 while 等流控制语句中使用非布尔值时, 最常发生类型转换错误。
*数据类型错误
*通信错误
  1. 第一种通信错误与格式不正确的 URL 或发送的数据有关。最常见的问题是在将数据发送给服务器 之前,没有使用 encodeURIComponent()对数据进行编码。

(6) 区分致命错误和非致命错误

  1. 非致命错误:
  • 不影响用户的主要任务;
  • 只影响页面的一部分;
  • 可以恢复;
  • 重复相同操作可以消除错误。
  1. 致命错误:
  • 应用程序根本无法继续运行;
  • 错误明显影响到了用户的主要操作;
  • 会导致其他连带错误。

(7) 把错误记录到服务器

3. 调试技术

(1) 将消息记录到控制台

  1. 通过 console 对象向 JavaScript 控制台中写入消息,这个对象具有下列方法:
  1. error(message):将错误消息记录到控制台
  2. info(message):将信息性消息记录到控制台
  3. log(message):将一般消息记录到控制台
  4. warn(message):将警告消息记录到控制台
  1. 通过 opera.postError()方法来访问。这个方法 接受一个参数,即要写入到控制台中的参数。
  2. 在 JavaScript 中运行 Java 代码。
function log(message){
         if (typeof console == "object"){
             console.log(message);
         } else if (typeof opera == "object"){
             opera.postError(message);
         } else if (typeof java == "object" && typeof java.lang == "object"){
        java.lang.System.out.println(message);
    }
}

function sum(num1, num2){
        log("Entering sum(), arguments are " + num1 + "," + num2);
    log("Before calculation");
    var result = num1 + num2;
    log("After calculation");
    log("Exiting sum()");
    return result;
}

(2) 将消息记录到当前页面

在页面中开辟一小块区域,用以显示消息。这个区域通常是一个 元素,而该元素可以总是出现在页面中,但仅用于调试目的;也可以是一个根据需要动态创建的元素。

function log(message){
    var console = document.getElementById("debuginfo");
    if (console === null){
        console = document.createElement("div");
        console.id = "debuginfo";
        console.style.background = "#dedede";
        console.style.border = "1px solid silver";
        console.style.padding = "5px";
        console.style.width = "400px";
        console.style.position = "absolute";
        console.style.right = "0px";
        console.style.top = "0px";
        document.body.appendChild(console);
  }
  console.innerHTML += "<p>" + message + "</p>";
}

(3) 抛出错误

对于大型应用程序来说,自定义的错误通常都使用 assert()函数抛出。这个函数接受两个参数, 一个是求值结果应该为 true 的条件,另一个是条件为 false 时要抛出的错误。

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;
}

4.常见的 IE 错误

(1) 操作终止

操作终止: 在修改尚未加载完成的页面时,就会发生操作终止错误。发生错误时, 会出现一个模态对话框,告诉你“操作终止。”单击确定(OK)按钮,则卸载整个页面,继而显示一张 空白屏幕。

当<script>节点被包含在某个元素中, 而且 JavaScript 代码又要使用 appendChild()、innerHTML 或其他 DOM 方法修改该元素的父元素或 祖先元素时,将会发生操作终止错误(因为只能修改已经加载完毕的元素)。

(2) 无效字符

所谓无效字符,就是 JavaScript 语法中未定义的字符。

(3) 未找到成员

如果在对象被销毁之后,又给该对象赋值,就会导致未找到成员错误。而导致这个错误 的,一定是 COM 对象。发生这个错误的最常见情形是使用 event 对象的时候。IE 中的 event 对象是 window 的属性,该对象在事件发生时创建,在最后一个事件处理程序执行完毕后销毁。假设你在一个 闭包中使用了 event 对象,而该闭包不会立即执行,那么在将来调用它并给 event 的属性赋值时,就 会导致未找到成员错误。

(4) 未知运行时错误

当使用 innerHTML 或 outerHTML 以下列方式指定 HTML 时,就会发生未知运行时错误(Unknown runtime error):一是把块元素插入到行内元素时,二是访问表格任意部分(<table>、<tbody>等)的 任意属性时。

(5) 语法错误

如果你引用了外部的 JavaScript 文件,而该文件最终并没有返回 JavaScript 代码,IE 也会抛出语法 错误。例如,<script>元素的 src 特性指向了一个 HTML 文件,就会导致语法错误。

(6) 系统无法找到指定资源

在使用 JavaScript 请求某个资源 URL,而该 URL 的长度超过了 IE 对 URL 最长不能超过 2083 个字符的限制时,就会发生这个错误。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,384评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,845评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,148评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,640评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,731评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,712评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,703评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,473评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,915评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,227评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,384评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,063评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,706评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,302评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,531评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,321评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,248评论 2 352

推荐阅读更多精彩内容