avaScript异常处理和调试
JavaScript异常处理
开发者也可以编写自己的异常,并像JavaScript自动抛出的异常一样显示。创建异常需要用到throw语句。
捕获异常语法:
try{
可能出现异常的语句或语句块
}
catch(err)
{
处理错误的语句或语句块
}
[finally {
无论是否有异常抛出或捕获都将执行的语句或语句块
}]
JavaScript捕获异常的说明:
try 和 catch 是成对出现的。try 语句允许我们定义在执行时进行错误测试的代码块。catch 语句允许我们定义当 try 代码块发生错误时,所执行的代码块。
在catch语句中可以对抛出的异常进行处理,而且后续的代码可以被继续运行不会受到影响。其中异常类型既可以是JavaScript内部的异常也可以是自己创建的异常
在异常处理中即使是很严重的语法错误,也不会导致程序中止。在try语句或语句块中可以包含多个throw语句,但是当执行到第一个throw语句时会直接跳转到catch中,不会继续执行try语句或语句块中的后续代码
在try代码中执行一次throw语句就不会再继续执行后续语句也不会抛出其他异常,因此在try语句中可以通过if语句来抛出不同种类的异常。但是当try代码中没有异常被抛出时则不运行catch语句中的代码。
finally语句
finally语句是用在try...catch语句之后用来执行异常处理后的代码的语句,不能单独使用,只能在try...catch语句后紧接着使用。无论try语句中是否有异常抛出,在try...catch语结束之后都会运行finally中的语句。finally语句可以省略。
try...catch语句 参见
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/try...catch
throw 语句允许我们创建自定义错误——用技术术语说:创建或抛出异常(exception)。语法:
throw expression;
其中
Expression 要抛出的表达式,指定了异常的内容,可以是 JavaScript 字符串、数字、逻辑值或对象。
或
throw new Error("错误信息")
throw语句用来抛出一个用户自定义的异常。当前函数的执行将被停止(throw之后的语句将不会执行),并且控制将被传递到调用堆栈(call stack)中的第一个catch块。如果调用者函数中没有catch块,程序将会终止。
throw语句 参见:
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/throw
如果把 throw 与 try 和 catch 一起使用,那么您能够控制程序流,并生成自定义的错误消息。
如:
抛出自定义错误的示例
// 定义函数
function round(num, d){
if(!isNaN(num) && !isNaN(d)){
num *= Math.pow(10, d);
return num;
}else{
// 抛出自定义错误
throw new Error("参数必须是数字");
}
}
// 调用函数
var d = parseInt(prompt('请输入数字'));
try{
alert(round(123.456, d));
}catch(err){
alert(err.message); // 接住抛出的自定义错误
}
下面再给出一个完整的例子:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>使用throw抛出异常并回应的例子</title>
</head>
<body>
<p>请输出一个 5 到 10 之间的数字:</p>
<input id="demo" type="text">
<button type="button" οnclick="myFunction()">测试输入</button>
<p id="message"></p>
<script>
function myFunction() {
var message, x;
message = document.getElementById("message");
message.innerHTML = "";
x = document.getElementById("demo").value;
try {
if(x == "") throw "值为空";
if(isNaN(x)) throw "不是数字";
x = Number(x);
if(x < 5) throw "太小";
if(x > 10) throw "太大";
}
catch(err) {
message.innerHTML = "错误: " + err;
}
}
</script>
</body>
</html>
保存文件名为:使用throw抛出异常并回应的例子.html,运行之,参见下图:
本例检测输入变量的值,你可以输入不同的值,单击“测试输入”试试,如果值是不符合要求,会抛出一个异常,catch 会捕捉到这个错误,并显示一段自定义的错误消息。
错误处理的原则
1.try中尽量少的包含语句
原因是因为,try语句要经过计算机的检测看看是否是错误的语句,如果是错误的语句则会执行catch里面的语句,如果try的语句过多的话,计算机处理速度就会变慢,影响程序的执行。
2.如果已经提前预知错误的类型,就用if...else...来代替try...catch
除掉错误预知的这个前提下,if..else..的用法与try...catch...的用法是基本相同的,严格意义来说,if..else..的可读性比try..catch..更强,语句理解能力也更好,开发人员与用户更加倾向于使用if..else.. 但是如果无法判断语句是否正确的话,仍然使用try..catch...会更加保险。
JavaScript 内置对象Error
Error 实例对象是最一般的错误类型,在它的基础上,JavaScript 还定义了其他派生错误对象,都是构造函数。
SyntaxError 对象是解析代码时发生的语法错误。
ReferenceError 对象是引用一个不存在的变量时发生的错误。
RangeError 对象是一个值超出有效范围时发生的错误。主要有几种情况,一是数组长度为负数,二是 Number 对象的方法参数超出范围,以及函数堆栈超过最大值。
TypeError 对象是变量或参数不是预期类型时发生的错误。比如,对字符串、布尔值、数值等原始类型的值使用 new 命令,就会抛出这种错误,因为 new 命令的参数应该是一个构造函数
URIError 对象是 URI 相关函数的参数不正确时抛出的错误,主要涉及encodeURI()、decodeURI()、encodeURIComponent()、decodeURIComponent()、escape()和unescape()这六个函数。
EvalError 对象
eval函数没有被正确执行时,会抛出EvalError错误。该错误类型已经不再使用了,只是为了保证与以前代码兼容,才继续保留。
开发者可以使用它们人为生成错误对象实例。如:
var err1 = new Error('出错了!');
var err2 = new RangeError('出错了,变量超出有效范围!');
var err3 = new TypeError('出错了,变量类型无效!');
err1.message // "出错了!"
err2.message // "出错了,变量超出有效范围!"
err3.message // "出错了,变量类型无效!"
对此不在多说,参见:
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Error
【另外、InternalError 对象表示出现在JavaScript引擎内部的错误。 例如: "InternalError: too much recursion"(内部错误:递归过深)。它是非标准的,请尽量不要在生产环境中使用它!https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/InternalError 】
JavaScript调试
JavaScript是解释型代码,代码执行到哪里,才调试到哪里,不像是C/C++,可以进行编译,链接,也不像是Python,进行预编译。通常,如果 JavaScript 出现错误,是不会有提示信息,幸运的是,很多浏览器都内置了调试工具。有了调试工具,我们就可以设置断点 (breakpoint、代码停止执行的位置), 且可以在代码执行时检测变量。
浏览器启用调试工具一般是按下 F12 键,打开 调试工具。
Console 对象
Console 对象用于 JavaScript 调试。
JavaScript 原生中默认是没有 Console 对象,这是宿主对象(也就是游览器)提供的内置对象。 用于访问调试控制台, 在不同的浏览器里效果可能不同。
Console 对象常见的两个用途:
显示网页代码运行时的错误信息。
提供了一个命令行接口,用来与网页代码互动。
打开开发者工具以后,顶端有多个面板,这里只介绍控制台(Console)面板,此面板基本上就是一个命令行窗口,你可以在提示符>后,输入代码,然后按回车(Enter键),代码就会执行。如果按Shift + Enter键,就是代码换行,不会触发执行(从而输入多行代码)。
Console 对象的方法
描述 | 实例 | |
assert() | ssert方法接受两个参数,第一个参数是表达式,第二个参数是字符串。只有当第一个参数为false,才会输出第二个参数,否则不会有任何结果。 | // 实例 console.assert(true === false, "判断条件不成立") // Assertion failed: 判断条件不成立 |
clear() | 清除当前控制台的所有输出,将光标回置到第一行。 | console.clear() |
count() | 用于计数,输出它被调用了多少次。 | (function() { for (var i = 0; i < 5; i++) { console.count('count'); } })(); |
error() | 输出信息时,在最前面加一个红色的叉,表示出错,同时会显示错误发生的堆栈。 | console.error("Error: %s (%i)", "Server is not responding",500) |
group() | 用于将显示的信息分组,可以把信息进行折叠和展开。 | console.group('第一层'); console.group('第二层');
console.log('error'); console.error('error'); console.warn('error');
console.groupEnd(); console.groupEnd(); |
groupCollapsed() | 与console.group方法很类似,唯一的区别是该组的内容,在第一次显示时是收起的(collapsed),而不是展开的。 | console.groupCollapsed('第一层'); console.groupCollapsed('第二层');
console.log('error'); console.error('error'); console.warn('error');
console.groupEnd(); console.groupEnd(); |
groupEnd() | 结束内联分组 | console.group('Group One'); console.group('Group Two');
// some code
console.groupEnd(); // Group Two 结束 console.groupEnd(); // Group One 结束 |
info() | console.log 别名,输出信息 | console.info("runoob") |
log() | 输出信息 | console.log("runoob") |
table() | 将复合类型的数据转为表格显示。 | var arr= [ { num: "1"}, { num: "2"}, { num: "3" } ]; console.table(arr);
var obj= { a:{ num: "1"}, b:{ num: "2"}, c:{ num: "3" } }; console.table(obj); |
time() | 计时开始 | console.time('计时器1'); for (var i = 0; i < 100; i++) { for (var j = 0; j < 100; j++) {} } console.timeEnd('计时器1'); console.time('计时器2'); for (var i = 0; i < 1000; i++) { for (var j = 0; j < 1000; j++) {} } console.timeEnd('计时器2'); |
timeEnd() | 计时结束 | console.time('计时器1'); for (var i = 0; i < 100; i++) { for (var j = 0; j < 100; j++) {} } console.timeEnd('计时器1'); console.time('计时器2'); for (var i = 0; i < 1000; i++) { for (var j = 0; j < 1000; j++) {} } console.timeEnd('计时器2'); |
trace() | 追踪函数的调用过程 | function d(a) { console.trace(); return a; } function b(a) { return c(a); } function c(a) { return d(a); } var a = b('123'); |
warn() | 输出警告信息 | console.warn("警告") |
最常用的就是 console.log()了。
console上述的集中度支持printf的占位符格式,支持的占位符有:字符(%s)、整数(%d或%i)、浮点数(%f)和对象(%o):
占位符 | 作用 |
%s | 字符串 |
%d or %i | 整数 |
%f | 浮点数 |
%o | 可展开的DOM |
%O | 列出DOM的属性 |
%c | 根据提供的css样式格式化字符串 |
实例
console.log("%d年%d月%d日",2018,7,26);
【附、清除控制台的历史记录
console.clear()
】
还可以设置断点,假设调试如下代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>断点测试示例</title>
</head>
<head>
</head>
<body>
<p id="demo"></p>
<p>注意这一行是否显示。</p>
<script>
var x = 15 * 5;
document.getElementById("demo").innerHTML = x;
</script>
</body>
</html>
保存文件名为:breakpoint测试示例.html
对于Edge浏览器,运行之,按下 F12 键,再安图示步骤操作,参见下图:
对于chrome浏览器,按下 F12 键,再安图示步骤操作,参见下图:
进一步学习可参见:
https://www.cnblogs.com/yzg1/p/5578363.html
https://blog.csdn.net/yin767833376/article/details/51656402
不再多说。
debugger 语句
当代码运行到debugger语句时,就会暂停运行,自动打开脚本源码界面。
for(var i = 0; i < 5; i++){
console.log(i);
if (i === 2) debugger;
}
上面代码打印出0,1,2以后,就会暂停,自动打开源码界面显示断点,等待进一步处理。参见下图: