搜索
首页web前端js教程JavaScript中的出色异常处理

Exceptional Exception Handling in JavaScript

核心要点

  • JavaScript 的异常处理通过“try…catch…finally”语句实现。“try”子句包含可能产生异常的代码,“catch”子句在发生异常时执行,“finally”子句无论结果如何都会执行。
  • JavaScript 有七个内置错误对象用于异常处理:Error、RangeError、ReferenceError、SyntaxError、TypeError、URIError 和 EvalError。每个对象代表一种特定类型的错误。
  • JavaScript 允许开发人员使用“throw”语句抛出自己的异常。这可以使代码更易于调试和维护,因为它允许创建有意义的错误消息。
  • 可以通过扩展现有的“Error”类型来创建自定义异常类型。这允许在复杂的应用程序中进行更具体和相关的错误处理。

软件开发中,墨菲定律同样适用:任何可能出错的事情,都会出错。对于非简单的程序,问题不是是否会出错,而是何时会出错。标准不兼容、不支持的功能和浏览器特性只是 web 开发人员面临的潜在问题的几个来源。鉴于可能出现的所有问题,JavaScript 却拥有一个令人惊讶的简单错误处理方法——它只是放弃并默默失败。至少,这是用户看到的行为。实际上,幕后发生了很多事情。

当 JavaScript 语句产生错误时,据说它抛出了一个异常。JavaScript 解释器不会继续执行下一条语句,而是检查异常处理代码。如果没有异常处理程序,则程序将从抛出异常的任何函数返回。这将对调用堆栈上的每个函数重复进行,直到找到异常处理程序或到达顶级函数,导致程序终止。

错误对象

发生异常时,会创建一个表示错误的对象并将其抛出。JavaScript 语言定义了七种类型的内置错误对象。这些错误类型是异常处理的基础。下面详细描述每种错误类型。

Error

“Error” 类型用于表示通用异常。此异常类型最常用于实现用户定义的异常。本文稍后将重新讨论创建用户定义异常的主题。“Error” 对象通过调用其构造函数来实例化,如下例所示:

var error = new Error("error message");

“Error” 对象包含两个属性,“name” 和“message”。“name” 属性指定异常类型(在本例中为“Error”)。“message” 属性提供对异常的更详细描述。“message” 从传递给异常构造函数的字符串中获取其值。其余异常类型表示更具体的错误类型,但它们的使用方式与通用“Error” 类型相同。

RangeError

当数字超出指定范围时,会生成“RangeError” 异常。例如,JavaScript 数字具有 toFixed() 方法,该方法采用“digits” 参数,表示小数点后出现的数字位数。此参数应在 0 到 20 之间(尽管某些浏览器支持更宽的范围)。如果“digits” 的值超出此范围,则会抛出“RangeError”。以下示例显示了这种情况。

var error = new Error("error message");

ReferenceError

当访问不存在的变量时,会抛出“ReferenceError” 异常。这些异常通常发生在拼写错误的现有变量名时。在下面的示例中,当访问“bar”时会发生“ReferenceError”。请注意,此示例假设在尝试递增操作时,“bar” 不存在于任何活动作用域中。

var pi = 3.14159;

pi.toFixed(100000);  // RangeError

SyntaxError

当违反 JavaScript 语言规则时,会抛出“SyntaxError”。熟悉 C 和 Java 等语言的开发人员习惯于在编译过程中遇到语法错误。但是,由于 JavaScript 是一种解释型语言,因此直到执行代码时才会识别语法错误。语法错误是独一无二的,因为它们是唯一一种无法从中恢复的异常类型。以下示例会生成语法错误,因为“if” 语句缺少右花括号。

function foo() {
  bar++;  // ReferenceError
}

TypeError

当值不是预期类型时,会发生“TypeError” 异常。尝试调用不存在的对象方法是此类异常的常见原因。以下示例创建一个名为“foo”的空对象,然后尝试调用其 bar() 方法。由于未定义 bar(),因此在尝试调用时会抛出“TypeError”。

if (foo) {  // SyntaxError
  // 缺少右花括号
}

URIError

当 encodeURI() 和 decodeURI() 等方法遇到格式错误的 URI 时,会抛出“URIError” 异常。以下示例在尝试解码字符串“%”时会生成“URIError”。“%” 字符表示 URI 转义序列的开头。由于在此示例中“%”之后没有任何内容,因此该字符串是无效的转义序列,因此是格式错误的 URI 组件。

var foo = {};

foo.bar(); // TypeError

EvalError

当 eval() 函数使用不当时,会抛出“EvalError” 异常。在最新版本的 EcmaScript 标准中未使用这些异常。但是,为了保持与旧版本标准的向后兼容性,它们仍然受支持。

处理异常

既然我们知道了异常是什么,那么现在就该学习如何阻止它们导致程序崩溃。JavaScript 通过“try…catch…finally”语句处理异常。下面显示了一个通用的示例语句。

decodeURIComponent("%"); // URIError

“try…catch…finally” 语句的第一部分是“try” 子句。“try” 子句是必需的,用于分隔程序员怀疑可能产生异常的代码块。“try” 子句后面必须跟有一个或两个“catch” 和“finally” 子句。

“catch” 子句

“try…catch…finally” 的第二部分是“catch” 子句。“catch” 子句是一段仅在“try” 子句中发生异常时才执行的代码块。尽管“catch” 子句是可选的,但如果没有它,就不可能真正处理异常。这是因为“catch” 子句阻止异常在调用堆栈中传播,从而允许程序恢复。如果“try” 块中发生异常,则控制权会立即传递给“catch” 子句。发生的异常也会传递到“catch” 块以进行处理。以下示例显示了如何使用“catch” 子句来处理“ReferenceError”。请注意,“ReferenceError” 对象可通过“exception” 变量在“catch” 子句中使用。

var error = new Error("error message");

复杂的应用程序可以生成各种异常。在这种情况下,可以使用“instanceof” 运算符来区分各种类型的异常。在以下示例中,假设“try” 子句可以生成几种类型的异常。相应的“catch” 子句使用“instanceof” 将“TypeError” 和“ReferenceError” 异常与所有其他类型的错误分开处理。

var pi = 3.14159;

pi.toFixed(100000);  // RangeError

“finally” 子句

“try…catch…finally” 语句的最后一个组件是可选的“finally” 子句。“finally” 子句是一段在“try” 和“catch” 子句之后执行的代码块,无论是否出现错误。“finally” 子句对于包含无论如何都需要执行的清理代码(关闭文件等)很有用。请注意,即使发生未捕获的异常,“finally” 子句也会执行。在这种情况下,“finally” 子句会执行,然后抛出的异常会正常继续。

关于“finally” 子句的一个有趣的说明是,即使“try” 或“catch” 子句执行“return” 语句,它也会执行。例如,以下函数返回 false,因为“finally” 子句是最后执行的内容。

function foo() {
  bar++;  // ReferenceError
}

抛出异常

JavaScript 允许程序员通过名为“throw” 的语句抛出自己的异常。这个概念对于没有经验的开发人员来说可能有点令人困惑。毕竟,开发人员努力编写没有错误的代码,但是“throw” 语句却故意引入错误。但是,故意抛出异常实际上可以使代码更易于调试和维护。例如,通过创建有意义的错误消息,可以更容易地识别和解决问题。

下面显示了“throw” 语句的几个示例。对可以作为异常抛出的数据类型没有限制。对可以捕获和抛出相同数据的次数也没有限制。换句话说,可以抛出异常,捕获异常,然后再次抛出异常。

if (foo) {  // SyntaxError
  // 缺少右花括号
}

虽然“throw” 语句可以与任何数据类型一起使用,但使用内置异常类型具有一定的优势。例如,Firefox 通过添加调试信息(例如发生异常的文件名和行号)来对这些对象进行特殊处理。

例如,假设您的应用程序中的某个地方发生了除法运算。由于可能出现除以零的情况,因此除法可能很麻烦。在 JavaScript 中,此类操作会导致“NaN”。这可能导致难以调试的令人困惑的结果。如果应用程序大声抱怨除以零,情况会简单得多。以下“if” 语句通过抛出异常来实现这一点。

var error = new Error("error message");

当然,使用“RangeError” 可能更合适,如下所示:

var pi = 3.14159;

pi.toFixed(100000);  // RangeError

自定义异常对象

我们刚刚学习了如何使用内置异常类型生成自定义错误消息。但是,另一种方法是通过扩展现有的“Error” 类型来创建新的异常类型。由于新类型继承自“Error”,因此它可以像其他内置异常类型一样使用。虽然本文不讨论 JavaScript 中的继承主题,但这里介绍了一种简单的技术。

以下示例将回到处理除以零的问题。我们不再像前面那样使用“Error” 或“RangeError” 对象,而是要创建我们自己的异常类型。在此示例中,我们正在创建“DivisionByZeroError” 异常类型。示例中的函数充当我们新类型的构造函数。构造函数负责分配“name” 和“message” 属性。示例的最后两行使新类型继承自“Error” 对象。

function foo() {
  bar++;  // ReferenceError
}

需要记住的事项

  • “try…catch…finally” 语句用于处理异常。
  • “try” 子句标识可能产生异常的代码。
  • “catch” 子句仅在发生异常时执行。
  • “finally” 子句始终执行,无论如何。
  • “throw” 语句用于生成异常。
  • 自定义异常对象应继承自现有的“Error” 类型。

图片来自 Fotolia

JavaScript 异常处理常见问题解答

JavaScript 中的语法错误和运行时错误有什么区别?

语法错误,也称为解析错误,在传统的编程语言中发生在编译时,在 JavaScript 中发生在解释时。当代码在语法上不正确且无法解析时,就会发生语法错误。例如,如果您忘记了右括号或使用了非法字符,则会发生语法错误。

另一方面,运行时错误发生在程序执行期间,在成功编译之后。这些错误通常是由于代码执行的非法操作造成的。例如,尝试访问未定义的变量或调用不存在的函数会导致运行时错误。

如何在 JavaScript 中处理异常?

JavaScript 提供 try…catch 语句来处理异常。try 块包含可能抛出异常的代码,而 catch 块包含如果 try 块中抛出异常将执行的代码。这是一个简单的示例:

var error = new Error("error message");

JavaScript 中“finally” 块的用途是什么?

JavaScript 中的“finally” 块用于在 try 和 catch 块之后执行代码,无论结果如何。这意味着无论是否抛出异常,“finally” 块中的代码都会执行。它通常用于在代码执行完毕后进行清理,例如关闭文件或清除资源。

我可以在 JavaScript 中抛出自己的异常吗?

是的,JavaScript 允许您使用“throw” 语句抛出自己的异常。您可以抛出任何类型的异常,包括字符串、数字、布尔值或对象。一旦抛出异常,程序的正常流程就会停止,控制权就会传递给最近的异常处理程序。

如何在 JavaScript 中创建自定义错误类型?

JavaScript 允许您通过扩展内置的 Error 对象来创建自定义错误类型。当您想要在代码中抛出特定类型的错误时,这很有用。这是一个示例:

var pi = 3.14159;

pi.toFixed(100000);  // RangeError

JavaScript 中的错误传播是什么?

错误传播是指将错误从抛出它的位置向上传递到调用堆栈中最近的异常处理程序的过程。如果在抛出错误的函数中没有捕获错误,它将向上传播到调用函数,依此类推,直到被捕获或到达全局范围,此时程序将终止。

如何在 JavaScript 中记录错误?

JavaScript 提供 console.error() 方法来记录错误。此方法的工作方式与 console.log() 相同,但它还在日志中包含堆栈跟踪,并在控制台中将消息突出显示为错误。这是一个示例:

function foo() {
  bar++;  // ReferenceError
}

JavaScript 中“null” 和“undefined” 有什么区别?

在 JavaScript 中,“null” 和“undefined” 都表示值的缺失。但是,它们在略微不同的上下文中使用。“Undefined” 表示已声明变量但尚未为其赋值。另一方面,“null” 是一个赋值值,表示没有值或没有对象。

如何在 JavaScript 中处理异步错误?

可以使用 JavaScript 中的 Promise 或 async/await 来处理异步错误。Promise 具有一个“catch” 方法,当 Promise 被拒绝时会调用该方法。使用 async/await,您可以像使用同步代码一样使用 try/catch 块。这是一个使用 async/await 的示例:

if (foo) {  // SyntaxError
  // 缺少右花括号
}

JavaScript 中的 TypeError 是什么?

当无法执行操作时,通常是当值不是预期类型时,就会在 JavaScript 中抛出 TypeError。例如,尝试调用非函数或访问未定义的属性会导致 TypeError。

以上是JavaScript中的出色异常处理的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
JavaScript框架:为现代网络开发提供动力JavaScript框架:为现代网络开发提供动力May 02, 2025 am 12:04 AM

JavaScript框架的强大之处在于简化开发、提升用户体验和应用性能。选择框架时应考虑:1.项目规模和复杂度,2.团队经验,3.生态系统和社区支持。

JavaScript,C和浏览器之间的关系JavaScript,C和浏览器之间的关系May 01, 2025 am 12:06 AM

引言我知道你可能会觉得奇怪,JavaScript、C 和浏览器之间到底有什么关系?它们之间看似毫无关联,但实际上,它们在现代网络开发中扮演着非常重要的角色。今天我们就来深入探讨一下这三者之间的紧密联系。通过这篇文章,你将了解到JavaScript如何在浏览器中运行,C 在浏览器引擎中的作用,以及它们如何共同推动网页的渲染和交互。JavaScript与浏览器的关系我们都知道,JavaScript是前端开发的核心语言,它直接在浏览器中运行,让网页变得生动有趣。你是否曾经想过,为什么JavaScr

node.js流带打字稿node.js流带打字稿Apr 30, 2025 am 08:22 AM

Node.js擅长于高效I/O,这在很大程度上要归功于流。 流媒体汇总处理数据,避免内存过载 - 大型文件,网络任务和实时应用程序的理想。将流与打字稿的类型安全结合起来创建POWE

Python vs. JavaScript:性能和效率注意事项Python vs. JavaScript:性能和效率注意事项Apr 30, 2025 am 12:08 AM

Python和JavaScript在性能和效率方面的差异主要体现在:1)Python作为解释型语言,运行速度较慢,但开发效率高,适合快速原型开发;2)JavaScript在浏览器中受限于单线程,但在Node.js中可利用多线程和异步I/O提升性能,两者在实际项目中各有优势。

JavaScript的起源:探索其实施语言JavaScript的起源:探索其实施语言Apr 29, 2025 am 12:51 AM

JavaScript起源于1995年,由布兰登·艾克创造,实现语言为C语言。1.C语言为JavaScript提供了高性能和系统级编程能力。2.JavaScript的内存管理和性能优化依赖于C语言。3.C语言的跨平台特性帮助JavaScript在不同操作系统上高效运行。

幕后:什么语言能力JavaScript?幕后:什么语言能力JavaScript?Apr 28, 2025 am 12:01 AM

JavaScript在浏览器和Node.js环境中运行,依赖JavaScript引擎解析和执行代码。1)解析阶段生成抽象语法树(AST);2)编译阶段将AST转换为字节码或机器码;3)执行阶段执行编译后的代码。

Python和JavaScript的未来:趋势和预测Python和JavaScript的未来:趋势和预测Apr 27, 2025 am 12:21 AM

Python和JavaScript的未来趋势包括:1.Python将巩固在科学计算和AI领域的地位,2.JavaScript将推动Web技术发展,3.跨平台开发将成为热门,4.性能优化将是重点。两者都将继续在各自领域扩展应用场景,并在性能上有更多突破。

Python vs. JavaScript:开发环境和工具Python vs. JavaScript:开发环境和工具Apr 26, 2025 am 12:09 AM

Python和JavaScript在开发环境上的选择都很重要。1)Python的开发环境包括PyCharm、JupyterNotebook和Anaconda,适合数据科学和快速原型开发。2)JavaScript的开发环境包括Node.js、VSCode和Webpack,适用于前端和后端开发。根据项目需求选择合适的工具可以提高开发效率和项目成功率。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

SecLists

SecLists

SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

Dreamweaver Mac版

Dreamweaver Mac版

视觉化网页开发工具