JavaScript基础——错误处理与测试

错误处理对于今天复杂的Web应用程序开发而言至关重要。

不能提前预测到可能发生的错误,不能提前采取回复策略,可能导致较差的用户体验,最终引发用户不满。

多数浏览器在默认情况下都不会向用户报告错误,因此在开发和调试期间需要启动浏览器的错误报告功能。

然而,在投入运行的产品代码中,则不应该再有诸如此类的错误报告出现。

下面是几种避免浏览器响应JavaScript错误的方法。

1)在可能发生错误的地方使用try-catch语句,这样你还有机会以适当的方式对错误给出响应,而不必沿用浏览器处理错误的机制;

2)使用window.onerror事件处理程序,这种方式可以接受try-catch不能处理的所有错误(仅限于IE、Firefox和Chrome)。

另外,对于Web应用程序都应该分析可能的错误来源,并制定处理错误的方案。

1)首先,必须要明确什么是致命错误,什么是非致命错误;

2)其次,再分析代码,以判断最可能发生的错误。JavaScript中发生错误的主要原因如下:

   2.1)类型转换

   2.2)未充分检测数据类型

   2.3)发送给服务器或从服务器接收到的数据有错误

IE、Firefox、Chrome、Opera和Safari都有JavaScript调试器,有的是内置的,有的是以需要下载的扩展形式存在的。这些调试器都支持设置断点、控制代码执行及在运行时检测变量的值。

/**
 *错误处理与调试
 */
function cl(x){
    console.log(x);
}
/**
 * 17.1 浏览器报告的错误
 */
//17.1.1 IE:工具——Internet选项——高级——显示每个脚本错误的通知
//17.1.2 Firefox:Firebug
//17.1.3 Safari:编辑——偏好设置——高级——在惨淡兰中显示"开发"菜单
//17.1.4 Opera
//17.1.5 Chrome:开发者工具栏

/**
 * 17.2 错误处理
 */
//17.2.1 try-catch语句
//错误消息的message属性
//17.2.1.1 finally子句
//17.2.1.2 错误类型
//Error、EvalError、RangeError、ReferenceError、SyntaxError、TypeError、URIError
//17.2.1.3 合理使用try-catch

//17.2.2 抛出错误
//通过原型链可以通过继承Error来创建自定义错误类型
function CustomError(message){
    this.name="CustomError";
    this.message=message;
}
CustomError.prototype=new Error();
//throw new CustomError("我错了");
//17.2.2.1 抛出错误的时机
function process(values){
    //自定义错误:参数不是数组则抛出异常
    if(!(values instanceof Array)){
        throw new Error("process():参数必须是数组类型");
    }
    values.sort();
    for(var i= 0,len=values.length;i<len;i++){
        if(values[i]>100){
            return values[i];
        }
    }
    return -1;
}
//17.2.2.2 抛出错误与使用try-catch
//捕获错误的目的在于避免浏览器以默认方式处理它们;
//而抛出错误的目的在于提供错误发生具体原因的消息。

//17.2.3 错误(error)事件
window.οnerrοr=function(message,url,line){
    alert(message);
    return false;
}
//图像也支持error事件
var image=new Image();
image.οnlοad=function(event){
    alert("图像加载了");
}
image.οnerrοr=function(event){
    alert("图像没有加载");
}
image.src="sim.gif";

//17.2.4 处理错误的策略

//17.2.5 常见的错误类型
//17.2.5.1 类型转换错误
//建议使用全等(===)和不全等(!==)操作符,以避免类型转换
//在流控制语句中,在条件比较时切实传入布尔值,可以避免类型转换错误
function concat(str1,str2,str3){
    var result=str1+str2;
    if(typeof str3=="string"){
        result+=str3;
    }
    return result;
}
//17.2.5.2 数据类型错误
//基本类型的值应该使用typeof来检测
//对象的值应该使用instanceof来检测
//例:获取一个url的?后的字符串
function getQueryString(url){
    if(typeof url=="string"){//通过检查类型确保安全
        var pos=url.indexOf("?");
        if(pos>-1){
            return url.substring(pos+1);
        }
    }
    return "";
}
//例:将一个数组反向排序
function reverseSort(values){
    if(values instanceof Array){//非数组值将被忽略
        values.sort();
        values.reverse();
    }
}
//17.2.5.3 通信错误
//处理查询字符串的函数
function addQueryStringArg(url,name,value){
    if(url.indexOf("?")==-1){
        url+="?";
    }else{
        url+="&"
    }
    url+=encodeURIComponent(name)+"="+encodeURIComponent(value);
    return url;
}
var url="http://www.baidu.com";
var newUrl=addQueryStringArg(url,"redir","http://www.sportsbaidu.com?a=b&c=d");
alert(newUrl);

//17.2.6 区分致命错误和非致命错误
//例:把所有模块的错误变成非致命的
var mods=[error1,error2,error3];
for(var i= 0,len=mods.length;i<len;i++){
    try{
        mods[i].init();
    }catch(ex){
        //处理错误
    }
}

//17.2.7 把错误记录到服务器
//类似以下函数从查询字符串中取得数据
function logError(sev,msg){
    var img=new Image();
    img.src="log.php?sev="+encodeURIComponent(sev)+"&msg="+encodeURIComponent(msg);
}
//使用try-catch语句,把相应错误记录到日志中
for(var i= 0,len=mods.length;i<len;i++){
    try{
        mods[i].init();
    }catch(ex){
        logError("nonfatal","Module init failed:"+ex.message);
    }
}

/**
 * 17.3 调试技术
 */
//17.3.1 将消息记录到控制台
//console对象有下列方法:error(msg)、info(msg)、log(msg)、warn(msg)
//不存在一种跨浏览器向JavaScript控制台写入消息的机制,但下面的函数可以作为统一的接口
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("传入的参数是:"+num1+","+num2);
    log("开始记录错误:");
    var result=num1+num2;
    log("结束记录错误");
    return result;
}

//17.3.2 将消息记录到当前页面

//17.3.3 抛出错误
//如果错误消息很具体,可抛出错误信息
function divide1(num1,num2){
    if(typeof num1!="number" || typeof num2 !="number"){
        throw new Error("divide1():两个参数必须都是数字");
    }
    return num1/num2;
}
function assert(condition,message){
    if(!condition){
        throw new Error(message);
    }
}
//对于大型应用程序来说,自定义的错误通常使用assert()函数抛出
function divide2(num1,num2){
    assert(typeof num1=="number" && typeof num2=="number",
    "divide2():两个参数必须都是数字");
    return num1/num2;
}

/**
 * 17.4 常见的IE错误
 */
//17.4.1 操作终止
//17.4.2 无效字符
//17.4.3 未找到成员
document.οnclick=function(){
    var event=window.event;
    setTimeout(function(){
        event.returnValue=false;//未找到成员错误
    },1000);
};
//17.4.4 未知运行时错误
//当使用innerHTML或outerHTML以下列方式指定HTML时,就会发生未知运行时错误:
//一是把块元素插入到行内元素时,二是访问表格任意部分的任意属性时
//17.4.5 语法错误
//17.4.6 系统无法找到指定资源



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值