【IT168 技术】就如IE10一样的大多数最新的浏览器,都支持允许Web开发者更快地诊断和修正bug的错误栈功能,尤其是对那些较难重现的Bug。开发者可以使用现在新浏览器强大的Web平台兼容性开发出和Windows8里面的app一样充满惊喜的APP。APP的强大和复杂的增长意味着开发者需要更好的工具来处理错误和诊断bug,如错误栈。在这篇文章里,我会演示一些简单的调试技术以帮助你节省时间。
调试程序
在Javascript中,结构化的异常处理通常可以通过异常的抛出和try/catch (开发人员可以定义一个错误,并通过一个控制程序处理这个错误)。当一个异常被抛出的时候,IE8的Javascript引擎Chakra可以捕捉到出错的位置和一系列的调用链,通常也被称为调用栈,如果一个错误对象被抛出(或者是一个原型链导致错误的函数), Chakra会为这个错误对象建立一个可读性比较好的列表来表现这个调用栈,这个栈包含了出错信息,函数名称以及在源文件中出错的行数。这些信息可以帮助开发人员可以通过查看被调用的函数快速的诊断程序中的缺陷,甚至可以直接看出哪行是有问题的代码,比如它可以指出传入某个函数中的参数是一个空值或者无效参数。
让我们来看下一个简单的示例脚本:计算(0,2)和(12,10)两点之间的距离:
'use strict';
function squareRoot(n) {
if (n < 0)
throw new Error('Cannot take square root of negative number.');
return Math.sqrt(n);
}
function square(n) {
return n * n;
}
function pointDistance(pt1, pt2) {
return squareRoot((pt1.x - pt2.x) + (pt1.y - pt2.y));
}
function sample() {
var pt1 = { x: 0, y: 2 };
var pt2 = { x: 12, y: 10 };
console.log('Distance is: ' + pointDistance(pt1, pt2));
}
try {
sample();
}
catch (e) {
console.log(e.stack);
}
})();
这段脚本有一个bug,它忘记了计算两个不同坐标之间差的平方。对于一些点的输入,函数pointDistance会返回错误的结果;其次,它会导致一个错误。要理解栈跟踪,我们在浏览器的开发者工具(F12激活)中的脚本标签中检查:
栈跟踪信息会在catch子句中记录到控制台中,同时,因为它是栈的最上方,它很容易就能看出来错误来源是在函数squareRoot。要调试这个问题,开发者一般不会在栈跟踪中挖得太深;函数squareRoot的前置条件已经违反了,同时往上一层看调用栈,它已经很清楚的表明:在调用squareRoot的子表达式同时需要是函数square的参数。
当调试的时候,通过在栈里设置一些断点能够帮助分析代码。请记住,还有其他方法去观察调用栈:举例来说,如果你设置了脚本调试器“在捕获异常时停止”模式,你就可以使用调试器来检查调用栈。对于已经发布了的程序,你可能考虑到把可能有问题的代码封装到try/catch块里,以便于捕获错误的调用,同时吧错误信息记录到你的服务器中。然后开发者能够观察调用栈信息来帮助隔离问题的区域。
DOM异常和错误栈
我前面提到过一个对象存在抛出时必须是有一个错误或者是一个可以追溯错误的原型链,这是有意为之的。javascript支持任何对象甚至是原型对象做为一个异常抛出,当这些对象都可以被捕获或者检查时,他们并非都是带有专门设计的包含错误或者特征信息的对象,因此,当抛出异常时,只有错误异常才会更新一个堆栈的属性。
虽然DOM异常也是对象,但他们没有追溯错误的原型链,因此他们就没有一个堆栈属性。当你执行DOM操作并且想显示出javascript兼容性的一些错误时,你可以在DOM操作代码上使用try/catch代码块,然后在catch语句内抛出一个新的异常:
try {
var div = document.createElement('div');
div.appendChild(div);
} catch (e) {
throw new Error(e.toString());
}
}
然而,你可能考虑你是否想用这种模式,它可能适用于那些通用库的开发;尤其是,考虑到你的代码意图是否想隐藏DOM的操作,或者是简单的执行一个任务。如果是隐藏DOM的操作,包裹操作部分并且抛出错误可能是最好的方式吧。