# JS错误处理与调试

# 17.1 浏览器报告的错误

本节讲如何一步一步打开各个主流浏览器的“开发者调试工具”,推荐直接在浏览器窗口按快捷键F12

# 17.2 错误处理

# 17.2.1 try-catch语句

1.try-catch语句标准模板:

try{
	// 可能会导致错误的代码
} catch(error){
	// 在错误发生时怎么处理
}
1
2
3
4
5

2.finally 子句 虽然在 try-catch 语句中是可选的,但finally 子句一经使用,其代码无论如何都会执行。参考代码:

function testFinally(){
	try {
		return 2;
	} catch (error){
		return 1;
	} finally {
		return 0;	   //尽管前面肯定有个return执行,但还是会执行此步,最终只会返回0
	}
}
1
2
3
4
5
6
7
8
9

3.错误类型 ECMA-262 定义了下列7 种错误类型:
 Error
 EvalError
 RangeError
 ReferenceError
 SyntaxError
 TypeError
 URIError

  • Error 是基类型,其他错误类型都继承自该类型。因此,所有错误类型共享了一组相同的属性(错误对象中的方法全是默认的对象方法)。Error 类型的错误很少见,如果有也是浏览器抛出的;这个基类型的主要目的是供开发人员抛出自定义错误。

  • EvalError 类型的错误会在使用eval()函数而发生异常时被抛出。简单地说,如果没有把eval()当成函数调用,就会抛出错误。在实际开发中极少会这样使用eval(),所以遇到这种错误类型的可能性极小。

  • RangeError 类型的错误会在数值超出相应范围时触发。

  • 在找不到对象的情况下,会发生ReferenceError(这种情况下,会直接导致人所共知的"object expected"浏览器错误)。通常,在访问不存在的变量时,就会发生这种错误。

  • 剩下的三个相应的就是语法错误、类型错误和URL错误。

# 17.2.2 抛出错误

与 try-catch 语句相配的还有一个throw 操作符,用于随时抛出自定义错误。抛出错误时,必须 要给throw 操作符指定一个值,这个值是什么类型,没有要求。下列代码都是有效的:

throw 12345;
throw "Hello world!";
throw true;
throw { name: "JavaScript"};
throw new Error("Something bad happened."); //使用内置错误类型,可以更真实地模拟浏览器错误
1
2
3
4
5

在遇到 throw 操作符时,代码会立即停止执行。仅当有try-catch 语句捕获到被抛出的值时,代 码才会继续执行。

# 17.2.3 错误(error)事件

任何没有通过try-catch 处理的错误都会触发window 对象的error 事件。在任何Web 浏览器中,onerror 事件处理程序都不会创建event 对象,但它可以接收三个参数:错误消息、错误所在的URL 和行号。

# 17.2.4 处理错误的策略

无重要内容。

# 17.2.5 常见的错误类型

由于JavaScript 是松散类型的,而且也不会验证函数的参数,因此错误只会在代码运行期间出现。一般来说,需要关注三种错误:
 类型转换错误
 数据类型错误
 通信错误
以上错误分别会在特定的模式下或者没有对值进行足够的检查的情况下发生。

  • 类型转换错误发生在使用某个操作符,或者使用其他可能会自动转换值的数据类型的语言结构时。

  • 数据类型错误最容易发生在将预料之外的值传递给函数的情况下。

  • 通信错误与格式不正确的URL 或发送的数据有关,另外,在服务器响应的数据不正确时,也会发生通信错误。

# 17.2.6 区分致命错误和非致命错误

区分非致命错误和致命错误的主要依据,就是看它们对用户的影响。

# 17.2.7 把错误记录到服务器

暂无使用过。

# 17.3 调试技术

不再建议在调试中使用alert()了,一方面比较麻烦(调试之后还需要清理),另一方面还可能引入新问题(想象一下把某个alert()函数遗留在产品代码中的结果,会打断用户操作)。

# 17.3.1 将消息记录到控制台

  1. console.error(message):将错误消息记录到控制台
  2. console.info(message):将信息性消息记录到控制台
  3. console.log(message):将一般消息记录到控制台
  4. console.warn(message):将警告消息记录到控制台

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

这种技术在不支持JavaScript 控制台的IE7 及更早版本或其他浏览器中十分有用。目前基本不适用。

# 17.3.3 抛出错误

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

function assert(condition, message){
	if (!condition){
	throw new Error(message);
	}
}
1
2
3
4
5

可以用这个assert()函数代替某些函数中需要调试的if 语句,以便输出错误消息。请看以下两个例子:

function divide(num1, num2){
	if (typeof num1 != "number" || typeof num2 != "number"){
		throw new Error("divide(): Both arguments must be numbers.");
	}
	return num1 / num2;
}
/* 这个简单的函数计算两个数的除法,在计算之前,必须先检测每个参数是否都是数值,不然如果有一个参数不是数
值,它会返回NaN。如果返回NaN,就会在Web 应用程序中导致问题 */
1
2
3
4
5
6
7
8
function divide(num1, num2){
	assert(typeof num1 == "number" && typeof num2 == "number",
			"divide(): Both arguments must be numbers.");
	return num1 / num2;
}
// 可见,使用assert()函数可以减少抛出错误所需的代码量,而且也比前面的代码更容易看懂。(个人并不觉得。。。)
1
2
3
4
5
6

# 17.4 常见的IE 错误

留待以后遇见补充。

Last Updated: 11/9/2022, 6:38:52 AM