双10期|基本对象Error及8种错误类型

本文详细介绍了JavaScript中的八种标准Error类型,包括基本Error、AggregateError、EvalError等,并提供了实例演示。理解并善用这些错误类型有助于异常处理和代码调试。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


theme: channing-cyan

highlight: a11y-dark

双10期|基本对象Error及8种错误类型

tips:每个技术点都值得优学优写:10期

好文推荐:

约2万字-Vue源码解读汇总篇(续更)

复盘基于进阶图的30+前端知识点

写在前面

错误对象是一种特殊的基本对象。它们拥有基本的 Error 类型,同时也有多种具体的错误类型。 认识他们,对于我们合理的处理异常,抛出异常,可能是有帮助的,对于深入认识 JavaScript 也是有帮助的,错误对象(错误类型)通常也是编程语言的重要组成部分。

JavaScript 种标准的具体的错误类型,主要有 8种:

  • AggregateError(实验中)
  • EvalError
  • InternalError
  • RangeError
  • ReferenceError
  • SyntaxError
  • TypeError
  • URIError

基本对象 Error

Error 简述

通过Error的构造器可以创建一个错误对象。当运行时错误产生时, Error的实例对象会被抛出。Error对象也可用于用户自定义的异常的基础对象。

下面是一个使用 Error 的示例:

js try { throw new Error('遇到了基本错误!') } catch (e) { console.error(e.name + ': ' + e.message) // 打印结果:Error: 遇到了基本错误! }

Error 的语法是:

// 中括号括起来的都是可选参数, // message:人类可阅读的关于错误的描述 // fileName(非标准):代码中导致异常的文件的文件名 // lineNumber(非标准):代码中导致异常的代码的行号 new EvalError([message[, fileName[, lineNumber]]])

正是因为一些 js 框架,合理使用了错误类型,我们在辨析错误的时候才方便了许多, 例如 message:错误描述,fileName:发生错误的文件名,lineNumber:代码中导致异常的代码的行号。 这些错误信息的提供,大大方便了定位排查。

下面是一个包含了基本的错误信息的控制台报错截图: image.png

自定义异常类型

如果你想要自定义基于 Error 的异常类型也是被支持的,但需要注意, 在FireFox中抛出自定义类型的异常可能会显示不正确的行号和文件名。

下面是一个示例:

```js function MyError (message) { this.name = 'MyError'; this.message = message || 'Default Message'; this.stack = (new Error()).stack; }

MyError.prototype = Object.create(Error.prototype); MyError.prototype.constructor = MyError;

try { throw new MyError(); } catch (e) { console.log(e.name); // 'MyError' console.log(e.message); // 'Default Message' }

try { throw new MyError('custom message'); } catch (e) { console.log(e.name); // 'MyError' console.log(e.message); // 'custom message' } ```

AggregateError

当多个错误需要包装在一个错误中时,可以考虑使用 AggregateError。

tips:这是一个实验中的功能.此功能某些浏览器尚在开发中,请参考浏览器兼容性, 在不同浏览器中使用适合的前缀。由于该功能对应的标准文档可能被重新修订, 所以在未来版本的浏览器中该功能的语法和行为可能随之改变。

语法:

// errors 错误的描述,默认为空。 // message 错误的提示信息。 new AggregateError(errors[, message])

tips:语法习惯上使用[]把可选内容包裹起来,例如上面,包括那个逗号都是可选的,都被[]包裹了。 这不仅仅是 javascript 这样做,所以什么是可选的,通常只要看是否被[]即可, 当然这是在遵守规范或约定的前提下。

下面是一个创建 AggregateError 的示例

js try { throw new AggregateError([ new Error("some error"), ], 'Hello'); } catch (e) { console.log(e instanceof AggregateError); // true console.log(e.message); // "Hello" console.log(e.name); // "AggregateError" console.log(e.errors); // [ Error: "some error" ] }

下面是一个捕获 AggregateError 的示例

js Promise.any([ Promise.reject(new Error("some error")), ]).catch(e => { console.log(e instanceof AggregateError); // true console.log(e.message); // "All Promises rejected" console.log(e.name); // "AggregateError" console.log(e.errors); // [ Error: "some error" ] });

EvalError

EvalError 表示一个关于 eval 函数的错误。 EvalError 不在当前ECMAScript规范中使用, 因此不会被运行时抛出. 但是对象本身仍然与规范的早期版本向后兼容。

语法:

// message:错误描述 // fileName:代码中导致异常的文件的文件名 // lineNumber:代码中导致异常的代码的行号 new EvalError([message[, fileName[, lineNumber]]])

下面是一个创建 EvalError 的示例

js try { throw new EvalError('Hello', 'someFile.js', 10); } catch (e) { console.log(e instanceof EvalError); // true console.log(e.message); // "Hello" console.log(e.name); // "EvalError" console.log(e.fileName); // "someFile.js" console.log(e.lineNumber); // 10 console.log(e.columnNumber); // 0 console.log(e.stack); // "@Scratchpad/2:2:9\n" }

tips:全局的 EvalError 对象本身不包含任何方法, 然而它通过原型链继承了一些方法。 也支持通过 prototype 向 EvalError 对象中添加自定义属性。

InternalError

InternalError 对象表示出现在 JavaScript引 擎内部的错误。 当 JavaScript 引擎出现内部错误时将会抛出InternalError。 例如: "InternalError: too much recursion"(内部错误:递归过深)。

tips:需要特别注意的是该特性是非标准的,所以应该谨慎在生产环境中使用它。

语法:

new InternalError([message[, fileName[, lineNumber]]])

一些适用场景:

  • "too many switch cases"(过多case子句);
  • "too many parentheses in regular expression"(正则表达式中括号过多);
  • "array initializer too large"(数组初始化器过大);
  • "too much recursion"(递归过深)。

RangeError

RangeError 对象表示范围越界错误,当一个值不在其所允许的范围或者集合中,可考虑使用它。

例如,试图传递一个 number 参数给一个范围内不包含该 number 的函数时则会引发 RangeError。 当传递一个不合法的 length 值作为 Array 构造器的参数创建数组, 或者传递错误值到数值计算方法(Number.toExponential(), Number.toFixed() ,Number.toPrecision()),会出现 RangeError。

语法:

new RangeError([message[, fileName[, lineNumber]]])

下面是一个使用 RangeError 的示例:

```js let MIN = 3, MAX = 10 let check = function (num) { if (num < MIN || num > MAX) { throw new RangeError('参数必须在这个区间:(' + MIN + ',' + MAX + ')'); } };

try { check(500); } catch (e) { if (e instanceof RangeError) { // 处理越界错误 console.error(e.name + ': ' + e.message) } } ```

ReferenceError

ReferenceError 用来表示引用类错误,ReferenceError 对象代表当一个不存在的变量被引用时发生的错误。 例如,当你尝试引用一个未被定义的变量时,将会抛出一个 ReferenceError 。

语法:

new ReferenceError([message[, fileName[, lineNumber]]])

下面是一个创建 ReferenceError 的示例

js try { throw new ReferenceError('引用错误', 'that-file.js', 250) } catch (e) { console.log(e instanceof ReferenceError) // true console.log(e.message) // 引用错误 console.log(e.name) // "ReferenceError" }

一个捕获 ReferenceError 的示例

js try { let a = username } catch (e) { console.log(e instanceof ReferenceError) // true console.log(e.message) // username is not defined console.log(e.name) // ReferenceError console.log(e.stack) // ReferenceError: username is not defined at ... }

JavaScript 种有一个“奇怪”的现象,就是“变量提升”,但这种提升又是有区别的, 例如在使用 let 声明一个变量前就使用它会被抛出一个 ReferenceError 异常,而使用 var 则不会抛出 ReferenceError。

下面是一个会抛出 ReferenceError 的示例。

js console.log(x) // ReferenceError let x = 2

image.png

SyntaxError

SyntaxError 语法错误,代表尝试解析语法上不合法的代码的错误。 当 Javascript 语言解析代码时,Javascript 引擎发现了不符合语法规范的的代码时时抛出 SyntaxError。

语法:

new SyntaxError([message[, fileName[, lineNumber]]])

下面是一个捕获 SyntaxError 的示例

js try { eval('hoo bar') } catch (e) { console.log(e instanceof SyntaxError) // true console.log(e.message) // Unexpected identifier console.log(e.name) // SyntaxError console.log(e.stack) // SyntaxError: Unexpected identifier at ... }

TypeError

TypeError 表示类型错误,表示值的类型不是预期类型时发生的错误。 例如,当传入函数的操作数或参数的类型并非操作符或函数所预期的类型时,将抛出一个 TypeError 类型错误。

语法:

new TypeError([message[, fileName[, lineNumber]]])

下面是一个捕获 TypeError 的示例

js try { null.f() } catch (e) { console.log(e instanceof TypeError) // true console.log(e.message) // Cannot read properties of null (reading 'f') console.log(e.name) // TypeError console.log(e.stack) // TypeError: Cannot read properties of null (reading 'f') at ... }

下面是一张关于先使用函数表达式,再去声明会被抛出 TypeError 的截图。

image.png

URIError

URIError 对象用来表示,以一种错误的方式使用全局 URI 处理函数,而产生的错误。 当向全局 URI 处理函数传递一个不合法的 URI 时,URIError 错误会被抛出。

语法:

new URIError([message[, fileName[, lineNumber]]])

下面是一个使用 URIError 的示例

js try { decodeURIComponent('%@资源地址') } catch (e) { console.log(e instanceof URIError) // true console.log(e.message) // URI malformed(畸形的,难看的) console.log(e.name) // URIError console.log(e.stack) // URIError: URI malformed at decodeURIComponent (<anonymous>) ... }

写在后面

关于 error 的使用,可能在一些应用的常规页面开发未必用得上, 但 JavaScript 是高级编程语言,它能做更多的事。就像是在写 java 接口时处理业务逻辑, 抛出适当的异常和捕获异常,可能是比较常见的事。如果 JavaScript 也做那样的事情, 那么 Error 相关的知识,结合 throw 语句抛出一个异常并且用 try...catch 语句捕获处理它, 就是常见的事了。

即使用得比较少,学习它,对于我们理解 JavaScript 和查看一些错误信息,排查定位 bug 也是有帮助的。

下面是一些在 vue3源码库 vue-next 种检索到的错误类型的应用的截图。 我曾写过 约2万字-Vue源码解读汇总篇(续更) , 而做这个的目的除了了解 vue,就是学习如何设计代码。例如本文的主角 Error 应该如何使用,我也会去该库检索学习。

image.png

image.png

image.png

### PyCharm 面向对象高级开发课程或报告示例 在 Python 的面向对象编程 (Object-Oriented Programming, OOP) 中,PyCharm 是一种功能强大且高效的集成开发环境 (IDE),能够显著提升开发者的工作效率。以下是关于 PyCharm 和 Python 面向对象高级开发的一些核心知识点和实践建议。 #### 1. 使用 PyCharm 进行类定义与调试 PyCharm 提供了许多内置工具来支持面向对象编程的核心概念,例如类的创建、继承关系的可视化以及方法重写提示等功能。通过这些特性,可以更轻松地实现复杂的类设计[^2]。 为了更好地利用 PyCharm,在编写类时可以通过快捷键 `Alt+Insert` 自动生成构造函数 (`__init__`) 及其他常用的方法模板。这不仅提高了编码速度,还能减少语法错误的发生概率。 #### 2. 继承与多态的实际应用 当涉及到复杂项目时,合理运用继承机制可以帮助我们构建模块化程度更高的应用程序。例如,在父类中定义通用属性和行为,而在子类里扩展特定的功能逻辑[^3]。与此同时,借助于动态绑定技术(即运行决定调用哪个具体实现),使得同一个接口可以根据不同类型的实例表现出多种形态—这就是所谓的“多态”。 此外,在实际操作过程中如果遇到难以理解的概念或者具体的代码片段无法正常工作的情况,则可充分利用 PyCharm 内置的帮助文档资源以及社区论坛寻求解决方案[^4]。 #### 3. 封装与访问控制 封装是保护内部状态免受外部干扰的重要手段之一。Python 并不像某些强类型语言那样严格区分公有(public)/私有(private)成员变量,而是采用约定俗成的方式(如单下划线 `_variable` 表示受保护字段;下划线 `__variable` 则触发名称改写从而达到类似效果)[^2] 。然而值得注意的是,尽管如此简单的设计哲学让学习曲线变得平缓许多,但对于大型团队协作而言仍需遵循一定的命名规范以免造成不必要的混乱。 另外值得一提的地方在于,虽然理论上任何地方都可以修改某个对象的状态信息,但从长远来看维持良好的抽象边界往往更有助于维护系统的稳定性与可靠性。 ```python class ParentClass: def __init__(self): self.public_var = "I'm public" self._protected_var = "I'm protected" self.__private_var = "I'm private" def get_private(self): return self.__private_var class ChildClass(ParentClass): pass child_instance = ChildClass() print(child_instance.public_var) # 输出: I'm public print(child_instance._protected_var) # 输出: I'm protected try: print(child_instance.__private_var) except AttributeError as e: print(e) # 报错: 'ChildClass' object has no attribute '__private_var' finally: print(child_instance.get_private())# 正确获取私有变量值: I'm private ``` #### 4. 实践案例分析 假设我们需要为一家电子商务平台开发一套商品管理系统。该系统应该具备以下基本功能:管理库存数量、记录销售历史并计算利润等等。此时就可以考虑基于 OOP 思想将其拆解成为若干独立但又相互关联的部分: - **Product**: 描述单一产品的基本信息及其价格; - **InventoryManager**: 负责跟踪每种产品当前可用的数量变化情况; - **SalesHistoryRecorder**: 存储每次交易详情以便后续统计分析之用。 以上述三个主要组件为例展示如何利用继承关系简化重复劳动的同时增强灵活性: ```python from datetime import datetime class Product: def __init__(self, name: str, price: float): self.name = name self.price = price def calculate_profit(self, cost_price:float)->float: """Calculate profit based on selling and buying prices.""" return round((self.price-cost_price)*100)/100 class InventoryItem(Product): def __init__(self,name:str ,price :float ,quantity:int=0 ): super().__init__(name,price ) self.quantity = quantity def update_stock(self,new_amount:int )->None : old_q=self .quantity self.quantity +=new_amount print(f"{abs(new_amount)} units of {self.name} added/removed from stock." f"(Previous:{old_q}, Now:{self.quantity})") class SaleRecord(InventoryItem ): def __init__(self,date_time=None,*args,**kwargs ) -> None : super(). __init__(*args,**kwargs ) now=datetime.now()if date_time is None else date_time self.date_time=str(now ) def record_sale(product_name,sale_qty,cost_per_unit,buying_rate ): item=next ((i for i in inventory if isinstance(i,InventoryItem )and i.name==product_name ),None ) if not item or sale_qty>item.quantity : raise ValueError('Insufficient Stock.') revenue=sale_qty*cost_per_unit total_cost=(sale_qty *buying_rate ) net_gain=revenue-total_cost updated_item=item.update_stock(-sale_qty ) new_record=SaleRecord(name=item.name, price=cost_per_unit , quantity=-sale_qty , date_time=datetime.today()) sales.append(new_record ) profits+=net_gain return {"Revenue":revenue,"Cost":total_cost ,"Profit":profits } ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值