JAVASCRIPT 基础教程
JAVASCRIPT & DOM
JAVASCRIPT & BOM
JAVASCRIPT 高级教程
JAVASCRIPT 示例
JAVASCRIPT 参考

JavaScript 错误处理

在本教程中,您将学习如何在 JavaScript 中优雅地处理错误。

错误处理

有时您的 JavaScript 代码运行不如预期顺利,从而导致错误。 有许多可能导致错误的原因,例如:

  • 网络连接问题
  • 用户可能在表单字段中输入了无效值
  • 引用不存在的对象或函数
  • 向网络服务器发送或接收的数据不正确
  • 应用程序需要访问的服务可能暂时不可用

这些类型的错误被称为运行时错误,因为它们发生在脚本运行时。专业的应用程序必须具有优雅地处理此类运行时错误的能力。通常这意味着更清楚、更准确地告知用户问题。

try...catch 语句

JavaScript 提供 try-catch 语句来捕获运行时错误,并优雅地处理它们。

任何可能抛出错误的代码都应该放在语句的try块中,处理错误的代码放在catch块中,如图所示:

try {
    // 可能导致错误的代码
} catch(error) {
    // 发生错误时要执行的操作
}

如果在 try 块中的任何一点发生错误,代码执行会立即从 try 块转移到 catch 块。 如果 try 块中没有发生错误,则 catch 块将被忽略,程序将在 try-catch 语句之后继续执行。

以下示例演示了 try-catch 语句的实际工作方式:

try {
    var greet = "Hi, there!";
    document.write(greet);
    
    // 试图访问一个不存在的变量
    document.write(welcome);
    
    // 如果发生错误,以下行将不会执行
    alert("All statements are executed successfully.");
} catch(error) {
    // 处理错误
  alert("Caught error: " + error.message);
}
 
// 继续执行
document.write("<p>Hello World!</p>");

上面的脚本将生成一个错误并显示在警告对话框中,而不是将其打印到浏览器控制台。 除此之外,即使发生错误,程序也没有突然停止。

另外,请注意 catch 关键字后跟括号中的标识符。 这个标识符就像一个函数参数。 发生错误时,JavaScript 解释器会生成一个包含有关它的详细信息的对象。 然后这个错误对象作为参数传递给 catch 进行处理。

提示: try-catch 语句是一种异常处理机制。 异常是指示在程序执行期间发生某种异常情况或错误的信号。 术语"异常"和"错误"经常互换使用。


try...catch...finally 语句

try-catch 语句也可以有一个finally 子句。 finally 块中的代码将始终执行,无论 try 块中是否发生错误。

以下示例将始终显示完成代码执行所花费的总时间。

// Assigning the value returned by the prompt dialog box to a variable
var num = prompt("Enter a positive integer between 0 to 100");

// 存储执行开始的时间
var start = Date.now();

try {
    if(num > 0 && num <= 100) {
        alert(Math.pow(num, num)); // the base to the exponent power
    } else {
        throw new Error("An invalid value is entered!");
    }
} catch(e) {
    alert(e.message);
} finally {
    // 显示执行代码所花费的时间
    alert("Execution took: " + (Date.now() - start) + "ms");
}

抛出错误

到目前为止,我们已经看到了 JavaScript 解析器在发生错误时自动抛出的错误。 但是,也可以使用 throw 语句手动抛出错误。

throw 语句的一般形式(或语法)是:throw expression;

expression 表达式可以是对象或任何数据类型的值。 但是,最好使用对象,最好使用 namemessage 属性。 JavaScript 内置的 Error() 构造函数提供了一种创建错误对象的便捷方式。 让我们看一些例子:

throw 123;
throw "Missing values!";
throw true;
throw { name: "InvalidParameter", message: "Parameter is not a number!" };
throw new Error("Something went wrong!");

注意: 如果您使用 JavaScript 内置的错误构造函数(例如 Error()TypeError() 等)来创建错误对象 ,则 name 属性与构造函数的名称相同,message 等于传递给构造函数的参数。

现在我们将创建一个函数 squareRoot() 来查找数字的平方根。 这可以通过使用 JavaScript 内置函数 Math.sqrt() 简单地完成,但这里的问题是,它返回 NaN 表示负数,而没有提供任何错误提示。

如果提供了负数,我们将通过引发自定义错误来解决此问题。

function squareRoot(number) {
    // 如果数字为负,则抛出错误
    if(number < 0) {
        throw new Error("Sorry, can't calculate square root of a negative number.");
    } else {
        return Math.sqrt(number);
    }
}
    
try {
    squareRoot(16);
    squareRoot(625);
    squareRoot(-9);
    squareRoot(100);
    
    // 如果抛出错误,以下行将不会执行
    alert("All calculations are performed successfully.");
} catch(e) {
    // 处理错误
    alert(e.message);
}

提示:理论上可以用虚数i计算负数的平方根,其中i2 = -1。 因此 -4 的平方根是 2i-9 的平方根是 3i,以此类推。 但是 JavaScript 不支持虚数。


错误类型

Error 对象是所有错误的基本类型,它有两个主要属性 — name 属性指定错误的类型message 属性保存更详细地描述错误的消息。 抛出的任何错误都将是 Error 对象的一个实例。

在 JavaScript 程序的执行过程中可能会出现几种不同类型的错误,例如 RangeErrorReferenceErrorSyntaxError TypeErrorURIError

以下部分更详细地描述了这些错误类型中的每一种:

RangeError

当您使用超出允许值范围的数字时,会引发 RangeError。 例如,创建一个负长度的数组会抛出 RangeError

var num = 12.735;
num.toFixed(200); // 抛出范围错误(允许范围从 0 到 100)

var array = new Array(-1); // 抛出范围错误

ReferenceError

当您尝试引用或访问不存在的变量或对象时,通常会抛出 ReferenceError。 以下示例显示了 ReferenceError 是如何发生的。

var firstName = "Harry";
console.log(firstname); // 抛出引用错误(变量名区分大小写)

undefinedObj.getValues(); // 抛出引用错误

nonexistentArray.length; // 抛出引用错误

SyntaxError

如果您的 JavaScript 代码中存在任何语法问题,则会在运行时抛出 SyntaxError。 例如,如果缺少右括号,则循环结构不正确,等等。

var array = ["a", "b", "c"];
document.write(array.slice(2); // 抛出语法错误(缺少括号)

alert("Hello World!'); // 抛出语法错误(引号不匹配)

TypeError

TypeError 当值不是预期类型时抛出。 例如,对数字调用字符串方法,对字符串调用数组方法等等。

var num = 123;
num.toLowerCase(); /* 抛出类型错误(因为 toLowerCase() 是一个字符串方法,数字不能转换为小写) */

var greet = "Hello World!"
greet.join() // 抛出类型错误(因为 join() 是一个数组方法)

URIError

当您为 URI 相关函数(例如 encodeURI()decodeURI())指定了无效的 URI(代表 统一资源标识符)时,将引发 URIError,如下所示:

var a = "%E6%A2%B";
decodeURI(a);  // 抛出 URI 错误

var b = "\uD800";
encodeURI(b);   // 抛出 URI 错误

注意:还有一种错误类型EvalError,当通过 eval() 函数执行代码时发生错误时抛出。 但是,这个错误不再由 JavaScript 抛出,但是这个对象仍然是为了向后兼容。

也可以使用它们各自的构造函数和 throw 语句手动抛出特定的错误类型,例如,要抛出 TypeError 您可以使用 TypeError() 构造函数,如下所示:

var num = prompt("Please enter a number");

try {
    if(num != "" && num !== null && isFinite(+num)) {
        alert(Math.exp(num));
    } else {
        throw new TypeError("You have not entered a number.");
    }
} catch(e) {
    alert(e.name);
    alert(e.message);
    alert(e.stack); // non-standard property
}

注意: Error 对象还支持一些非标准属性。 最广泛使用的此类属性之一是:stack,它返回该错误的堆栈跟踪。 您可以将其用于调试目的,但不要在生产站点上使用它。

Advertisements