From f86d238fa4b52adbe2e1aaea50bcba779bb635a7 Mon Sep 17 00:00:00 2001 From: Hank Date: Wed, 6 Jun 2018 12:20:00 +0800 Subject: [PATCH 01/18] Update task.md --- .../2-custom-errors/1-format-error/task.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/1-js/08-error-handling/2-custom-errors/1-format-error/task.md b/1-js/08-error-handling/2-custom-errors/1-format-error/task.md index 2c8e910fc0..d45bc1ea45 100644 --- a/1-js/08-error-handling/2-custom-errors/1-format-error/task.md +++ b/1-js/08-error-handling/2-custom-errors/1-format-error/task.md @@ -2,13 +2,13 @@ importance: 5 --- -# Inherit from SyntaxError +# 继承 SyntaxError -Create a class `FormatError` that inherits from the built-in `SyntaxError` class. +创造一个继承自内建类 `SyntaxError` 的 `FormatError` 类。 -It should support `message`, `name` and `stack` properties. +它应该支持 `message`、 `name` 和 `stack` 属性。 -Usage example: +用例: ```js let err = new FormatError("formatting error"); From 4346ba2f333e10da5beee1e4fc84d32ff4c40b2d Mon Sep 17 00:00:00 2001 From: Hank Date: Wed, 6 Jun 2018 12:21:54 +0800 Subject: [PATCH 02/18] Update task.md --- 1-js/08-error-handling/2-custom-errors/1-format-error/task.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/08-error-handling/2-custom-errors/1-format-error/task.md b/1-js/08-error-handling/2-custom-errors/1-format-error/task.md index d45bc1ea45..f49caea0ac 100644 --- a/1-js/08-error-handling/2-custom-errors/1-format-error/task.md +++ b/1-js/08-error-handling/2-custom-errors/1-format-error/task.md @@ -18,5 +18,5 @@ alert( err.name ); // FormatError alert( err.stack ); // stack alert( err instanceof FormatError ); // true -alert( err instanceof SyntaxError ); // true (because inherits from SyntaxError) +alert( err instanceof SyntaxError ); // true (因为它继承自 SyntaxError) ``` From 85c1f801aa61522810f59767099aa83ce00c24ee Mon Sep 17 00:00:00 2001 From: Hank Date: Wed, 6 Jun 2018 12:28:54 +0800 Subject: [PATCH 03/18] Update article.md --- .../2-custom-errors/article.md | 91 ++++++++++--------- 1 file changed, 47 insertions(+), 44 deletions(-) diff --git a/1-js/08-error-handling/2-custom-errors/article.md b/1-js/08-error-handling/2-custom-errors/article.md index d7d61166dd..ed14a16c45 100644 --- a/1-js/08-error-handling/2-custom-errors/article.md +++ b/1-js/08-error-handling/2-custom-errors/article.md @@ -1,33 +1,33 @@ -# Custom errors, extending Error +# 自定义以及拓展错误 -When we develop something, we often need our own error classes to reflect specific things that may go wrong in our tasks. For errors in network operations we may need `HttpError`, for database operations `DbError`, for searching operations `NotFoundError` and so on. +当我们在进行开发的时候,通常需要属于我们自己的错误类来反映任务中可能出现的特殊情况。对于网络操作错误,我们需要 `HttpError`,对于数据库操作错误,我们需要 `DbError`,对于搜索操作错误,我们需要 `NotFoundError`,等等。 -Our errors should support basic error properties like `message`, `name` and, preferably, `stack`. But they also may have other properties of their own, e.g. `HttpError` objects may have `statusCode` property with a value like `404` or `403` or `500`. +我们自定义的错误应该具有基本的错误属性,例如 `message`、`name` 以及更加详细的 `stack`。但是它们也会有属于自己的属性。举个例子,`HttpError`对象会有一个 `statusCode` 属性,取值可能为 `404`、`403` 或 `500` 等。 -JavaScript allows to use `throw` with any argument, so technically our custom error classes don't need to inherit from `Error`. But if we inherit, then it becomes possible to use `obj instanceof Error` to identify error objects. So it's better to inherit from it. +JavaScript 允许我们在使用 `throw` 时带任何参数,所以从技术层面上说,我们自定义的错误不需要继承 `Error` 类,但如果我们继承了这个类,就能使用 `obj instanceof Error` 来鉴别错误对象,所以我们最好继承它。 -As we build our application, our own errors naturally form a hierarchy, for instance `HttpTimeoutError` may inherit from `HttpError`, and so on. +在我们进行开发时,我们自己的异常类通常是有层次结构的,例如 `HttpTimeoutError` 可能继承自 `HttpError` 等。 -## Extending Error +## 可扩展错误 -As an example, let's consider a function `readUser(json)` that should read JSON with user data. +让我们用一个能够读取用户数据的函数 `readUser(json)` 来作为例子。 -Here's an example of how a valid `json` may look: +这里是一个可用的 `json` 的例子: ```js let json = `{ "name": "John", "age": 30 }`; ``` -Internally, we'll use `JSON.parse`. If it receives malformed `json`, then it throws `SyntaxError`. +在这里面,我们使用 `JSON.parse`。如果它接收到错误的 `json`,就会抛出 `SyntaxError`。 -But even if `json` is syntactically correct, that doesn't mean that it's a valid user, right? It may miss the necessary data. For instance, if may not have `name` and `age` properties that are essential for our users. +但即使是格式正确的 `json`,也并不表示它就是可用的,对吧?它有可能会遗漏一些必要的数据。例如,缺失了对用户有必要的 `name` 和 `age` 属性。 -Our function `readUser(json)` will not only read JSON, but check ("validate") the data. If there are no required fields, or the format is wrong, then that's an error. And that's not a `SyntaxError`, because the data is syntactically correct, but another kind of error. We'll call it `ValidationError` and create a class for it. An error of that kind should also carry the information about the offending field. +函数 `readUser(json)` 不止会读取 JSON,也会检查(验证)数据的。如果没有所需要的属性,或者格式不正确,就会发生错误。而这不是 `SyntaxError`,因为数据在语法上时正确的,但是有其他的错误。我们称之为 `ValidationError` 并且为之创建一个类。这种类型的错误也应该承载缺少的字段的信息。 -Our `ValidationError` class should inherit from the built-in `Error` class. +我们的 `ValidationError` 类应该继承自内置的 `Error` 类。 -That class is built-in, but we should have its approximate code before our eyes, to understand what we're extending. + `Error` 类是内置的,但是我们需要看一下大致的代码,来理解我们需要扩展什么。 -So here you are: +代码如下: ```js // The "pseudocode" for the built-in Error class defined by JavaScript itself @@ -40,7 +40,7 @@ class Error { } ``` -Now let's go on and inherit `ValidationError` from it: +现在让我们开始用 `ValidationError` 来进行继承: ```js run untrusted *!* @@ -65,12 +65,13 @@ try { } ``` -Please take a look at the constructor: +来看看构造器: -1. In the line `(1)` we call the parent constructor. JavaScript requires us to call `super` in the child constructor, so that's obligatory. The parent constructor sets the `message` property. -2. The parent constructor also sets the `name` property to `"Error"`, so in the line `(2)` we reset it to the right value. +1. 行 `(1)` 被称为父类构造器。JavaScript 需要我们在子类构造器中调用 `super`,这是强制性的。父类构造器设定 `message` 属性。 -Let's try to use it in `readUser(json)`: +2. 父类构造器也设定 `name` 的值为 `"Error"`,所以在行 `(2)` 我们将其重置为正确的值 + +让我们用 `readUser(json)` 来试试: ```js run class ValidationError extends Error { @@ -111,11 +112,11 @@ try { } ``` -The `try..catch` block in the code above handles both our `ValidationError` and the built-in `SyntaxError` from `JSON.parse`. + `try..catch` 代码块处理 `ValidationError` 和来自 `JSON.parse` 的内置 `SyntaxError`。 -Please take a look at how we use `instanceof` to check for the specific error type in the line `(*)`. +接下来看看我们是如何使用 `instanceof` 来检测行 `(*)` 中的特定错误类型。 -We could also look at `err.name`, like this: +也看看 `err.name`,就像这样: ```js // ... @@ -124,13 +125,13 @@ We could also look at `err.name`, like this: // ... ``` -The `instanceof` version is much better, because in the future we are going to extend `ValidationError`, make subtypes of it, like `PropertyRequiredError`. And `instanceof` check will continue to work for new inheriting classes. So that's future-proof. +使用 `instanceof` 的做法会好很多,因为我们在以后会扩展 `ValidationError`,创造一个它的子类型,例如 `PropertyRequiredError`。而 `instanceof` 对于新的继承类也适用。所以这是个长远的保证。 -Also it's important that if `catch` meets an unknown error, then it rethrows it in the line `(**)`. The `catch` only knows how to handle validation and syntax errors, other kinds (due to a typo in the code or such) should fall through. +还有一点很重要,在 `catch` 语句捕捉到未知的错误时,它会抛出在行 `(**)` 处重新抛出,`catch` 语句仅仅知道如何处理验证和语法错误,而其他错误不应该被捕获。 -## Further inheritance +## 更进一步的继承 -The `ValidationError` class is very generic. Many things may go wrong. The property may be absent or it may be in a wrong format (like a string value for `age`). Let's make a more concrete class `PropertyRequiredError`, exactly for absent properties. It will carry additional information about the property that's missing. + `ValidationError` 类是十分通用的。因此可能会在某些方面出错。属性可能缺失,格式可能发生错误(例如 `age` 属性的值为一个字符串)。让我们来创造一个更加具体的类 `PropertyRequiredError`,为属性缺失的错误而量身定做的。它将会承载属性缺失的相关信息。 ```js run class ValidationError extends Error { @@ -183,13 +184,13 @@ try { } ``` -The new class `PropertyRequiredError` is easy to use: we only need to pass the property name: `new PropertyRequiredError(property)`. The human-readable `message` is generated by the constructor. +这个 `PropertyRequiredError` 十分容易上手:我们只需要传递属性名:`new PropertyRequiredError(property)`。易懂的 `message` 属性将会由构造器提供。 -Please note that `this.name` in `PropertyRequiredError` constructor is again assigned manually. That may become a bit tedius -- to assign `this.name = ` when creating each custom error. But there's a way out. We can make our own "basic error" class that removes this burden from our shoulders by using `this.constructor.name` for `this.name` in the constructor. And then inherit from it. +需要注意的是,在 `PropertyRequiredError` 构造器中的 `this.name` 是再次进行手动赋值的。这可能会造成冗余 —— 在创建每个自定义错误的时候都要进行赋值 `this.name = `。但这并不是唯一的办法。我们可以创建自己的“基础异常”类,通过将 `this.constructor.name` 赋值给 `this.name`,然后再进行继承。 -Let's call it `MyError`. +我们称其为 `MyError`。 -Here's the code with `MyError` and other custom error classes, simplified: +这是 `MyError` 以及其他自定义错误类的代码: ```js run class MyError extends Error { @@ -214,19 +215,19 @@ class PropertyRequiredError extends ValidationError { alert( new PropertyRequiredError("field").name ); // PropertyRequiredError ``` -Now custom errors are much shorter, especially `ValidationError`, as we got rid of the `"this.name = ..."` line in the constructor. +现在的自定义错误更加的简洁,特别是 `ValidationError`,我们在其构造器中删除了 `"this.name = ..."` 这一行。 -## Wrapping exceptions +## 包装异常 -The purpose of the function `readUser` in the code above is "to read the user data", right? There may occur different kinds of errors in the process. Right now we have `SyntaxError` and `ValidationError`, but in the future `readUser` function may grow: the new code will probably generate other kinds of errors. +上述代码中的函数 `readUser` 的目的就是“读取用户数据”,对吧?在此过程中可能会出现多个不同类型的异常,目前我们有 `SyntaxError` 和 `ValidationError`,但在将来,函数 `readUser` 将会不断壮大,新添加的代码或许会导致其他类型的异常。 -The code which calls `readUser` should handle these errors. Right now it uses multiple `if` in the `catch` block to check for different error types and rethrow the unknown ones. But if `readUser` function generates several kinds of errors -- then we should ask ourselves: do we really want to check for all error types one-by-one in every code that calls `readUser`? +调用函数 `readUser` 的代码要能够处理这些异常。现在它在 `catch` 语句块中使用多个 `if` 语句来检测不同类型的异常以及抛出未知异常。但如果函数 `readUser` 抛出了多种异常 —— 我们扪心自问:我们真的需要一个接一个地处理它抛出的异常吗? -Often the answer is "No": the outer code wants to be "one level above all that". It wants to have some kind of "data reading error". Why exactly it happened -- is often irrelevant (the error message describes it). Or, even better if there is a way to get error details, but only if we need to. +答案是 “No”:外部代码想要比其他代码更高一级。它想要一些类似于关于数据读取的异常,其错误描述信息通常是不相关的。或者,如果能有一种获取异常的细节的办法就更好了,但这仅限于我们需要的时候。 -So let's make a new class `ReadError` to represent such errors. If an error occurs inside `readUser`, we'll catch it there and generate `ReadError`. We'll also keep the reference to the original error in its `cause` property. Then the outer code will only have to check for `ReadError`. +所以,我们创建一个 `ReadError` 类来表现上述的异常。如果在函数 `readUser` 中发生了异常,我们会将其捕获,并生成 `ReadError`。我们同时也会在其 `cause` 属性中保留对原始异常的引用。那么外部的代码就只需要检测 `ReadError`。 -Here's the code that defines `ReadError` and demonstrates its use in `readUser` and `try..catch`: +下面的代码定义 `ReadError` 以及演示如何 `readUser` 和 `try..catch` 中使用它: ```js run class ReadError extends Error { @@ -294,14 +295,16 @@ try { } ``` -In the code above, `readUser` works exactly as described -- catches syntax and validation errors and throws `ReadError` errors instead (unknown errors are rethrown as usual). +上述代码中, `readUser` 正如描述的一样正常工作 —— 捕获语法以及验证的异常并且使用抛出 `ReadError`用来代替之前的行为(未知的异常依旧重新抛出)。 + +所以外部代码负责检测 `instanceof ReadError`,不必列出所有可能的异常类型。 + +这种途径称为“包装异常”,因为我们将“低级别的异常”包装为 `ReadError` ,这会使得调用代码更加的方便。它在面向对象编程中广泛使用。 -So the outer code checks `instanceof ReadError` and that's it. No need to list possible all error types. +## 总结 -The approach is called "wrapping exceptions", because we take "low level exceptions" and "wrap" them into `ReadError` that is more abstract and more convenient to use for the calling code. It is widely used in object-oriented programming. +- 我们能够继承 `Error` 以及其他内置的类,只需要注意 `name` 属性以及调用 `super`。 -## Summary +- 大多数时候,我们应该使用 `instanceof` 来检测一些特定的异常。它也能够在继承中使用。但有时我们会发现来自第三方库的异常,并且不容易得到它的类。那么 `name` 属性就可用于这一类的检测。 -- We can inherit from `Error` and other built-in error classes normally, just need to take care of `name` property and don't forget to call `super`. -- Most of the time, we should use `instanceof` to check for particular errors. It also works with inheritance. But sometimes we have an error object coming from the 3rd-party library and there's no easy way to get the class. Then `name` property can be used for such checks. -- Wrapping exceptions is a widespread technique when a function handles low-level exceptions and makes a higher-level object to report about the errors. Low-level exceptions sometimes become properties of that object like `err.cause` in the examples above, but that's not strictly required. +- 包装异常是一种广泛应用的技术,当一个函数处理低级别的异常时,用一个高级别的对象来报告错误。低级别的异常有时会变成这个对象的属性,就像上面例子中的 `err.cause`,但这不是严格的要求。 From 25c1afc8fb31822e6262841e93e4c0654a69c2d7 Mon Sep 17 00:00:00 2001 From: Hank Date: Wed, 6 Jun 2018 12:29:20 +0800 Subject: [PATCH 04/18] Update task.md --- 1-js/08-error-handling/2-custom-errors/1-format-error/task.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/08-error-handling/2-custom-errors/1-format-error/task.md b/1-js/08-error-handling/2-custom-errors/1-format-error/task.md index f49caea0ac..f6d12fe358 100644 --- a/1-js/08-error-handling/2-custom-errors/1-format-error/task.md +++ b/1-js/08-error-handling/2-custom-errors/1-format-error/task.md @@ -4,7 +4,7 @@ importance: 5 # 继承 SyntaxError -创造一个继承自内建类 `SyntaxError` 的 `FormatError` 类。 +创造一个继承自内置类 `SyntaxError` 的 `FormatError` 类。 它应该支持 `message`、 `name` 和 `stack` 属性。 From b48753874bfd3b34b81190a4406910cd836ff92a Mon Sep 17 00:00:00 2001 From: Hank Date: Wed, 6 Jun 2018 12:32:23 +0800 Subject: [PATCH 05/18] =?UTF-8?q?=E8=87=AA=E5=AE=9A=E4=B9=89=E4=BB=A5?= =?UTF-8?q?=E5=8F=8A=E6=8B=93=E5=B1=95=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 自定义以及拓展错误 --- 1-js/08-error-handling/2-custom-errors/article.md | 1 + 1 file changed, 1 insertion(+) diff --git a/1-js/08-error-handling/2-custom-errors/article.md b/1-js/08-error-handling/2-custom-errors/article.md index ed14a16c45..b1ddc4e588 100644 --- a/1-js/08-error-handling/2-custom-errors/article.md +++ b/1-js/08-error-handling/2-custom-errors/article.md @@ -308,3 +308,4 @@ try { - 大多数时候,我们应该使用 `instanceof` 来检测一些特定的异常。它也能够在继承中使用。但有时我们会发现来自第三方库的异常,并且不容易得到它的类。那么 `name` 属性就可用于这一类的检测。 - 包装异常是一种广泛应用的技术,当一个函数处理低级别的异常时,用一个高级别的对象来报告错误。低级别的异常有时会变成这个对象的属性,就像上面例子中的 `err.cause`,但这不是严格的要求。 + From 37a2ec40974ad69c3bccd46dfb59c6bb062b0cc3 Mon Sep 17 00:00:00 2001 From: Hank Date: Wed, 6 Jun 2018 12:32:48 +0800 Subject: [PATCH 06/18] =?UTF-8?q?=E8=87=AA=E5=AE=9A=E4=B9=89=E4=BB=A5?= =?UTF-8?q?=E5=8F=8A=E6=8B=93=E5=B1=95=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 自定义以及拓展错误 From 8846ac9b0544d88f6a5cca7366932dd6356a7f94 Mon Sep 17 00:00:00 2001 From: Hank Date: Wed, 6 Jun 2018 12:33:20 +0800 Subject: [PATCH 07/18] =?UTF-8?q?=E7=BB=A7=E6=89=BF=20SyntaxError?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 继承 SyntaxError From 9ad042569956bc0d2855710ad1a8903fe98b43cc Mon Sep 17 00:00:00 2001 From: Hank Date: Wed, 6 Jun 2018 12:33:34 +0800 Subject: [PATCH 08/18] =?UTF-8?q?=E7=BB=A7=E6=89=BF=20SyntaxError?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 继承 SyntaxError --- 1-js/08-error-handling/2-custom-errors/1-format-error/task.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/08-error-handling/2-custom-errors/1-format-error/task.md b/1-js/08-error-handling/2-custom-errors/1-format-error/task.md index f6d12fe358..ac24fae1ca 100644 --- a/1-js/08-error-handling/2-custom-errors/1-format-error/task.md +++ b/1-js/08-error-handling/2-custom-errors/1-format-error/task.md @@ -19,4 +19,4 @@ alert( err.stack ); // stack alert( err instanceof FormatError ); // true alert( err instanceof SyntaxError ); // true (因为它继承自 SyntaxError) -``` +``` From d88517c618eeb992908a8766f569f333d3fae29d Mon Sep 17 00:00:00 2001 From: Hank Date: Wed, 6 Jun 2018 12:33:46 +0800 Subject: [PATCH 09/18] Update task.md --- 1-js/08-error-handling/2-custom-errors/1-format-error/task.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/08-error-handling/2-custom-errors/1-format-error/task.md b/1-js/08-error-handling/2-custom-errors/1-format-error/task.md index ac24fae1ca..4fd852eddd 100644 --- a/1-js/08-error-handling/2-custom-errors/1-format-error/task.md +++ b/1-js/08-error-handling/2-custom-errors/1-format-error/task.md @@ -17,6 +17,6 @@ alert( err.message ); // formatting error alert( err.name ); // FormatError alert( err.stack ); // stack -alert( err instanceof FormatError ); // true +alert( err instanceof FormatError ); // truea alert( err instanceof SyntaxError ); // true (因为它继承自 SyntaxError) ``` From 80169478fa9632f77aa88322091e0fd34b596c29 Mon Sep 17 00:00:00 2001 From: Hank Date: Wed, 6 Jun 2018 12:33:57 +0800 Subject: [PATCH 10/18] =?UTF-8?q?=E7=BB=A7=E6=89=BF=20SyntaxError?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 继承 SyntaxError --- 1-js/08-error-handling/2-custom-errors/1-format-error/task.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/08-error-handling/2-custom-errors/1-format-error/task.md b/1-js/08-error-handling/2-custom-errors/1-format-error/task.md index 4fd852eddd..ac24fae1ca 100644 --- a/1-js/08-error-handling/2-custom-errors/1-format-error/task.md +++ b/1-js/08-error-handling/2-custom-errors/1-format-error/task.md @@ -17,6 +17,6 @@ alert( err.message ); // formatting error alert( err.name ); // FormatError alert( err.stack ); // stack -alert( err instanceof FormatError ); // truea +alert( err instanceof FormatError ); // true alert( err instanceof SyntaxError ); // true (因为它继承自 SyntaxError) ``` From 66e5ef1e5c3730b0f1563169f4c862f0987560a9 Mon Sep 17 00:00:00 2001 From: Hank Date: Wed, 6 Jun 2018 12:37:52 +0800 Subject: [PATCH 11/18] =?UTF-8?q?=E8=87=AA=E5=AE=9A=E4=B9=89=E4=BB=A5?= =?UTF-8?q?=E5=8F=8A=E6=8B=93=E5=B1=95=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 自定义以及拓展错误 --- 1-js/08-error-handling/2-custom-errors/article.md | 1 - 1 file changed, 1 deletion(-) diff --git a/1-js/08-error-handling/2-custom-errors/article.md b/1-js/08-error-handling/2-custom-errors/article.md index b1ddc4e588..9ea84805f6 100644 --- a/1-js/08-error-handling/2-custom-errors/article.md +++ b/1-js/08-error-handling/2-custom-errors/article.md @@ -68,7 +68,6 @@ try { 来看看构造器: 1. 行 `(1)` 被称为父类构造器。JavaScript 需要我们在子类构造器中调用 `super`,这是强制性的。父类构造器设定 `message` 属性。 - 2. 父类构造器也设定 `name` 的值为 `"Error"`,所以在行 `(2)` 我们将其重置为正确的值 让我们用 `readUser(json)` 来试试: From 8c078f8cd1a7a762cf7e9af4124219334e4c4a1f Mon Sep 17 00:00:00 2001 From: Hank Date: Wed, 6 Jun 2018 12:38:55 +0800 Subject: [PATCH 12/18] =?UTF-8?q?=E8=87=AA=E5=AE=9A=E4=B9=89=E4=BB=A5?= =?UTF-8?q?=E5=8F=8A=E6=8B=93=E5=B1=95=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 自定义以及拓展错误 --- 1-js/08-error-handling/2-custom-errors/article.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/1-js/08-error-handling/2-custom-errors/article.md b/1-js/08-error-handling/2-custom-errors/article.md index 9ea84805f6..c7bd9efb00 100644 --- a/1-js/08-error-handling/2-custom-errors/article.md +++ b/1-js/08-error-handling/2-custom-errors/article.md @@ -303,8 +303,5 @@ try { ## 总结 - 我们能够继承 `Error` 以及其他内置的类,只需要注意 `name` 属性以及调用 `super`。 - - 大多数时候,我们应该使用 `instanceof` 来检测一些特定的异常。它也能够在继承中使用。但有时我们会发现来自第三方库的异常,并且不容易得到它的类。那么 `name` 属性就可用于这一类的检测。 - - 包装异常是一种广泛应用的技术,当一个函数处理低级别的异常时,用一个高级别的对象来报告错误。低级别的异常有时会变成这个对象的属性,就像上面例子中的 `err.cause`,但这不是严格的要求。 - From a89c7d2083fff827efed65846ae98719c36910fc Mon Sep 17 00:00:00 2001 From: Hank Date: Mon, 11 Jun 2018 12:15:23 +0800 Subject: [PATCH 13/18] =?UTF-8?q?=E6=A0=B9=E6=8D=AE=E6=A0=A1=E5=AF=B9?= =?UTF-8?q?=E6=84=8F=E8=A7=81=E8=BF=9B=E8=A1=8C=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 1-js/08-error-handling/2-custom-errors/1-format-error/task.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/08-error-handling/2-custom-errors/1-format-error/task.md b/1-js/08-error-handling/2-custom-errors/1-format-error/task.md index ac24fae1ca..d2feea44b8 100644 --- a/1-js/08-error-handling/2-custom-errors/1-format-error/task.md +++ b/1-js/08-error-handling/2-custom-errors/1-format-error/task.md @@ -6,7 +6,7 @@ importance: 5 创造一个继承自内置类 `SyntaxError` 的 `FormatError` 类。 -它应该支持 `message`、 `name` 和 `stack` 属性。 +它应该支持 `message`, `name` 和 `stack` 属性。 用例: From f8e07989a0f4301798ceb057e6b1c225a59c3951 Mon Sep 17 00:00:00 2001 From: Hank Date: Mon, 11 Jun 2018 12:26:41 +0800 Subject: [PATCH 14/18] =?UTF-8?q?=E6=A0=B9=E6=8D=AE=E6=A0=A1=E5=AF=B9?= =?UTF-8?q?=E6=84=8F=E8=A7=81=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 1-js/08-error-handling/2-custom-errors/article.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/1-js/08-error-handling/2-custom-errors/article.md b/1-js/08-error-handling/2-custom-errors/article.md index c7bd9efb00..9d2ff451ad 100644 --- a/1-js/08-error-handling/2-custom-errors/article.md +++ b/1-js/08-error-handling/2-custom-errors/article.md @@ -1,8 +1,8 @@ -# 自定义以及拓展错误 +# 自定义以及继承错误 当我们在进行开发的时候,通常需要属于我们自己的错误类来反映任务中可能出现的特殊情况。对于网络操作错误,我们需要 `HttpError`,对于数据库操作错误,我们需要 `DbError`,对于搜索操作错误,我们需要 `NotFoundError`,等等。 -我们自定义的错误应该具有基本的错误属性,例如 `message`、`name` 以及更加详细的 `stack`。但是它们也会有属于自己的属性。举个例子,`HttpError`对象会有一个 `statusCode` 属性,取值可能为 `404`、`403` 或 `500` 等。 +我们自定义的错误应该具有基本的错误属性,例如 `message`,`name` 以及更加详细的 `stack`。但是它们也会有属于自己的属性。举个例子,`HttpError`对象会有一个 `statusCode` 属性,取值可能为 `404`、`403` 或 `500` 等。 JavaScript 允许我们在使用 `throw` 时带任何参数,所以从技术层面上说,我们自定义的错误不需要继承 `Error` 类,但如果我们继承了这个类,就能使用 `obj instanceof Error` 来鉴别错误对象,所以我们最好继承它。 @@ -21,7 +21,7 @@ let json = `{ "name": "John", "age": 30 }`; 但即使是格式正确的 `json`,也并不表示它就是可用的,对吧?它有可能会遗漏一些必要的数据。例如,缺失了对用户有必要的 `name` 和 `age` 属性。 -函数 `readUser(json)` 不止会读取 JSON,也会检查(验证)数据的。如果没有所需要的属性,或者格式不正确,就会发生错误。而这不是 `SyntaxError`,因为数据在语法上时正确的,但是有其他的错误。我们称之为 `ValidationError` 并且为之创建一个类。这种类型的错误也应该承载缺少的字段的信息。 +函数 `readUser(json)` 不仅会读取 JSON,也会检查(验证)数据。如果没有所需要的属性,或者格式不正确,就会发生错误。而这不是 `SyntaxError`,因为数据在语法上时正确的,但是有其他的错误。我们称之为 `ValidationError` 并且为之创建一个类。这种类型的错误也应该承载缺少的字段的信息。 我们的 `ValidationError` 类应该继承自内置的 `Error` 类。 @@ -126,7 +126,7 @@ try { 使用 `instanceof` 的做法会好很多,因为我们在以后会扩展 `ValidationError`,创造一个它的子类型,例如 `PropertyRequiredError`。而 `instanceof` 对于新的继承类也适用。所以这是个长远的保证。 -还有一点很重要,在 `catch` 语句捕捉到未知的错误时,它会抛出在行 `(**)` 处重新抛出,`catch` 语句仅仅知道如何处理验证和语法错误,而其他错误不应该被捕获。 +还有一点很重要,在 `catch` 语句捕捉到未知的错误时,它会在抛出行 `(**)` 处重新抛出,`catch` 语句仅仅知道如何处理验证和语法错误,而其他错误不应该被捕获。 ## 更进一步的继承 @@ -185,7 +185,7 @@ try { 这个 `PropertyRequiredError` 十分容易上手:我们只需要传递属性名:`new PropertyRequiredError(property)`。易懂的 `message` 属性将会由构造器提供。 -需要注意的是,在 `PropertyRequiredError` 构造器中的 `this.name` 是再次进行手动赋值的。这可能会造成冗余 —— 在创建每个自定义错误的时候都要进行赋值 `this.name = `。但这并不是唯一的办法。我们可以创建自己的“基础异常”类,通过将 `this.constructor.name` 赋值给 `this.name`,然后再进行继承。 +需要注意的是,在 `PropertyRequiredError` 构造器中的 `this.name` 是再次进行手动赋值的。这可能会造成冗余 —— 在创建每个自定义错误的时候都要进行赋值 `this.name = `。但这并不是唯一的办法。我们可以创建自己的“基础异常”类,通过将 `this.constructor.name` 赋值给 `this.name` 来卸下我们肩上的负担,然后再进行继承。 我们称其为 `MyError`。 @@ -294,11 +294,11 @@ try { } ``` -上述代码中, `readUser` 正如描述的一样正常工作 —— 捕获语法以及验证的异常并且使用抛出 `ReadError`用来代替之前的行为(未知的异常依旧重新抛出)。 +上述代码中, `readUser` 正如描述的一样正常工作 —— 捕获语法以及验证的异常并且使用抛出 `ReadError` 异常用来代替之前的行为(未知的异常依旧重新抛出)。 所以外部代码负责检测 `instanceof ReadError`,不必列出所有可能的异常类型。 -这种途径称为“包装异常”,因为我们将“低级别的异常”包装为 `ReadError` ,这会使得调用代码更加的方便。它在面向对象编程中广泛使用。 +这种途径称为“包装异常”,因为我们将“低级别的异常”包装为 `ReadError`,这会使得调用代码更加的抽象和方便。它在面向对象编程中被广泛使用。 ## 总结 From ddf833f89190b452dbf6c5fe0f4202ec6e0cad99 Mon Sep 17 00:00:00 2001 From: Hank Date: Tue, 12 Jun 2018 23:42:43 +0800 Subject: [PATCH 15/18] =?UTF-8?q?=E6=A0=B9=E6=8D=AE=E6=A0=A1=E5=AF=B9?= =?UTF-8?q?=E6=84=8F=E8=A7=81=E4=BF=AE=E6=94=B9=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2-custom-errors/article.md | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/1-js/08-error-handling/2-custom-errors/article.md b/1-js/08-error-handling/2-custom-errors/article.md index 9d2ff451ad..8ea27fb40e 100644 --- a/1-js/08-error-handling/2-custom-errors/article.md +++ b/1-js/08-error-handling/2-custom-errors/article.md @@ -1,4 +1,4 @@ -# 自定义以及继承错误 +# 自定义错误及扩展错误 当我们在进行开发的时候,通常需要属于我们自己的错误类来反映任务中可能出现的特殊情况。对于网络操作错误,我们需要 `HttpError`,对于数据库操作错误,我们需要 `DbError`,对于搜索操作错误,我们需要 `NotFoundError`,等等。 @@ -8,7 +8,7 @@ JavaScript 允许我们在使用 `throw` 时带任何参数,所以从技术层 在我们进行开发时,我们自己的异常类通常是有层次结构的,例如 `HttpTimeoutError` 可能继承自 `HttpError` 等。 -## 可扩展错误 +## 扩展错误 让我们用一个能够读取用户数据的函数 `readUser(json)` 来作为例子。 @@ -19,9 +19,9 @@ let json = `{ "name": "John", "age": 30 }`; 在这里面,我们使用 `JSON.parse`。如果它接收到错误的 `json`,就会抛出 `SyntaxError`。 -但即使是格式正确的 `json`,也并不表示它就是可用的,对吧?它有可能会遗漏一些必要的数据。例如,缺失了对用户有必要的 `name` 和 `age` 属性。 +但即使是格式正确的 `json`,也并不表示它就是可用的,对吧?它有可能会遗漏一些必要的数据。例如,缺失了对用户所必需的 `name` 和 `age` 属性。 -函数 `readUser(json)` 不仅会读取 JSON,也会检查(验证)数据。如果没有所需要的属性,或者格式不正确,就会发生错误。而这不是 `SyntaxError`,因为数据在语法上时正确的,但是有其他的错误。我们称之为 `ValidationError` 并且为之创建一个类。这种类型的错误也应该承载缺少的字段的信息。 +函数 `readUser(json)` 不仅会读取 JSON,也会检查(验证)数据。如果没有所需要的字段,或者格式不正确,那也是错误。而这不是 `SyntaxError`,因为数据在语法上是正确的,但是有其他的错误。我们称之为 `ValidationError` 并且为之创建一个类。这种类型的错误也应该承载缺少的字段的信息。 我们的 `ValidationError` 类应该继承自内置的 `Error` 类。 @@ -30,12 +30,12 @@ let json = `{ "name": "John", "age": 30 }`; 代码如下: ```js -// The "pseudocode" for the built-in Error class defined by JavaScript itself +// 由JavaScript本身定义的内置错误类“伪代码” class Error { constructor(message) { this.message = message; - this.name = "Error"; // (different names for different built-in error classes) - this.stack = ; // non-standard, but most environments support it + this.name = "Error"; //(不同内置错误类别的名称) + this.stack = ; // 非标准,但大多数环境支持它 } } ``` @@ -60,8 +60,8 @@ try { test(); } catch(err) { alert(err.message); // Whoops! - alert(err.name); // ValidationError - alert(err.stack); // a list of nested calls with line numbers for each + alert(err.name); // 验证错误 + alert(err.stack); // 每个行编号的嵌套调用列表 } ``` @@ -94,24 +94,24 @@ function readUser(json) { return user; } -// Working example with try..catch +// try..catch 实例 try { let user = readUser('{ "age": 25 }'); } catch (err) { if (err instanceof ValidationError) { *!* - alert("Invalid data: " + err.message); // Invalid data: No field: name + alert("Invalid data: " + err.message); // 无效的数据:缺失字段:name */!* } else if (err instanceof SyntaxError) { // (*) alert("JSON Syntax Error: " + err.message); } else { - throw err; // unknown error, rethrow it (**) + throw err; // 未知错误,再次抛出(**) } } ``` - `try..catch` 代码块处理 `ValidationError` 和来自 `JSON.parse` 的内置 `SyntaxError`。 +上面的 `try..catch` 代码块同时处理我们的 `ValidationError` 和来自 `JSON.parse` 的内置 `SyntaxError`。 接下来看看我们是如何使用 `instanceof` 来检测行 `(*)` 中的特定错误类型。 @@ -126,7 +126,7 @@ try { 使用 `instanceof` 的做法会好很多,因为我们在以后会扩展 `ValidationError`,创造一个它的子类型,例如 `PropertyRequiredError`。而 `instanceof` 对于新的继承类也适用。所以这是个长远的保证。 -还有一点很重要,在 `catch` 语句捕捉到未知的错误时,它会在抛出行 `(**)` 处重新抛出,`catch` 语句仅仅知道如何处理验证和语法错误,而其他错误不应该被捕获。 +还有一点很重要,在 `catch` 语句捕捉到未知的错误时,它会在抛出行 `(**)` 处重新抛出,`catch` 语句仅仅知道如何处理验证和语法错误,而其他错误(代码中的打印错误等)不应该被捕获。 ## 更进一步的继承 @@ -164,21 +164,21 @@ function readUser(json) { return user; } -// Working example with try..catch +// try..catch实例 try { let user = readUser('{ "age": 25 }'); } catch (err) { if (err instanceof ValidationError) { *!* - alert("Invalid data: " + err.message); // Invalid data: No property: name - alert(err.name); // PropertyRequiredError + alert("Invalid data: " + err.message); // 无效的数据:缺失属性:name + alert(err.name); // 必有属性错误 alert(err.property); // name */!* } else if (err instanceof SyntaxError) { alert("JSON Syntax Error: " + err.message); } else { - throw err; // unknown error, rethrow it + throw err; // 未知错误,再次抛出 } } ``` @@ -211,7 +211,7 @@ class PropertyRequiredError extends ValidationError { } // name is correct -alert( new PropertyRequiredError("field").name ); // PropertyRequiredError +alert( new PropertyRequiredError("field").name ); // 必有属性错误 ``` 现在的自定义错误更加的简洁,特别是 `ValidationError`,我们在其构造器中删除了 `"this.name = ..."` 这一行。 @@ -222,11 +222,11 @@ alert( new PropertyRequiredError("field").name ); // PropertyRequiredError 调用函数 `readUser` 的代码要能够处理这些异常。现在它在 `catch` 语句块中使用多个 `if` 语句来检测不同类型的异常以及抛出未知异常。但如果函数 `readUser` 抛出了多种异常 —— 我们扪心自问:我们真的需要一个接一个地处理它抛出的异常吗? -答案是 “No”:外部代码想要比其他代码更高一级。它想要一些类似于关于数据读取的异常,其错误描述信息通常是不相关的。或者,如果能有一种获取异常的细节的办法就更好了,但这仅限于我们需要的时候。 +通常答案是 “No”:外部代码想要比其他代码更高一级。它想要一些类似于“数据读取异常“的东西。它为什么发生 —— (其错误描述信息)通常是不相关的。或者,如果能有一种获取异常细节的办法就更好了,但这仅限于我们需要的时候。 所以,我们创建一个 `ReadError` 类来表现上述的异常。如果在函数 `readUser` 中发生了异常,我们会将其捕获,并生成 `ReadError`。我们同时也会在其 `cause` 属性中保留对原始异常的引用。那么外部的代码就只需要检测 `ReadError`。 -下面的代码定义 `ReadError` 以及演示如何 `readUser` 和 `try..catch` 中使用它: +下面的代码定义了 `ReadError` ,并演示了如何在 `readUser` 和 `try..catch` 中使用它: ```js run class ReadError extends Error { @@ -285,7 +285,7 @@ try { if (e instanceof ReadError) { *!* alert(e); - // Original error: SyntaxError: Unexpected token b in JSON at position 1 + // 原错误:语法错误:在位置1处不应有 b alert("Original error: " + e.cause); */!* } else { @@ -294,14 +294,14 @@ try { } ``` -上述代码中, `readUser` 正如描述的一样正常工作 —— 捕获语法以及验证的异常并且使用抛出 `ReadError` 异常用来代替之前的行为(未知的异常依旧重新抛出)。 +上述代码中, `readUser` 正如描述的一样正常工作 —— 捕获语法以及验证的异常并且抛出 `ReadError` 异常用来代替之前的行为(未知的异常依旧重新抛出)。 所以外部代码负责检测 `instanceof ReadError`,不必列出所有可能的异常类型。 -这种途径称为“包装异常”,因为我们将“低级别的异常”包装为 `ReadError`,这会使得调用代码更加的抽象和方便。它在面向对象编程中被广泛使用。 +这种途径称为“包装异常”,因为我们将“低级别的异常”包装为 `ReadError`,使得调用代码更加抽象和方便。它在面向对象编程中被广泛使用。 ## 总结 -- 我们能够继承 `Error` 以及其他内置的类,只需要注意 `name` 属性以及调用 `super`。 +- 我们能够正常地继承 `Error` 以及其他内置的错误类,只需要注意 `name` 属性以及不要忘了调用 `super`。 - 大多数时候,我们应该使用 `instanceof` 来检测一些特定的异常。它也能够在继承中使用。但有时我们会发现来自第三方库的异常,并且不容易得到它的类。那么 `name` 属性就可用于这一类的检测。 -- 包装异常是一种广泛应用的技术,当一个函数处理低级别的异常时,用一个高级别的对象来报告错误。低级别的异常有时会变成这个对象的属性,就像上面例子中的 `err.cause`,但这不是严格的要求。 +- 包装异常是一种广泛应用的技术,当一个函数处理低级别的异常时,用一个高级别的对象来报告错误。低级别的异常有时会变成这个对象的属性,就像上面例子中的 `err.cause`,但这并不严格要求。 From 8d3291b4735fbdb41935c83fe90bfd4f9306584b Mon Sep 17 00:00:00 2001 From: Hank Date: Tue, 19 Jun 2018 10:40:02 +0800 Subject: [PATCH 16/18] =?UTF-8?q?=E6=A0=B9=E6=8D=AE=E6=A0=A1=E9=98=9F?= =?UTF-8?q?=E6=84=8F=E8=A7=81=E8=BF=9B=E8=A1=8C=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 1-js/08-error-handling/2-custom-errors/1-format-error/task.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/08-error-handling/2-custom-errors/1-format-error/task.md b/1-js/08-error-handling/2-custom-errors/1-format-error/task.md index d2feea44b8..01c964a458 100644 --- a/1-js/08-error-handling/2-custom-errors/1-format-error/task.md +++ b/1-js/08-error-handling/2-custom-errors/1-format-error/task.md @@ -6,7 +6,7 @@ importance: 5 创造一个继承自内置类 `SyntaxError` 的 `FormatError` 类。 -它应该支持 `message`, `name` 和 `stack` 属性。 +它应该支持 `message`,`name` 和 `stack` 属性。 用例: From b7cb61b4f8f580e114c206aac3f9111ee06c9657 Mon Sep 17 00:00:00 2001 From: Hank Date: Tue, 19 Jun 2018 10:41:11 +0800 Subject: [PATCH 17/18] =?UTF-8?q?=E6=A0=B9=E6=8D=AE=E6=A0=A1=E9=98=9F?= =?UTF-8?q?=E6=84=8F=E8=A7=81=E8=BF=9B=E8=A1=8C=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 1-js/08-error-handling/2-custom-errors/1-format-error/task.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/1-js/08-error-handling/2-custom-errors/1-format-error/task.md b/1-js/08-error-handling/2-custom-errors/1-format-error/task.md index 01c964a458..36fd27a41b 100644 --- a/1-js/08-error-handling/2-custom-errors/1-format-error/task.md +++ b/1-js/08-error-handling/2-custom-errors/1-format-error/task.md @@ -18,5 +18,5 @@ alert( err.name ); // FormatError alert( err.stack ); // stack alert( err instanceof FormatError ); // true -alert( err instanceof SyntaxError ); // true (因为它继承自 SyntaxError) -``` +alert( err instanceof SyntaxError ); // true(因为它继承自 SyntaxError) +``` From 1d86710422ccc941bb1fe5e34cb60aabe77d9a34 Mon Sep 17 00:00:00 2001 From: Hank Date: Tue, 19 Jun 2018 10:45:18 +0800 Subject: [PATCH 18/18] =?UTF-8?q?=E6=A0=B9=E6=8D=AE=E6=A0=A1=E9=98=9F?= =?UTF-8?q?=E6=84=8F=E8=A7=81=E8=BF=9B=E8=A1=8C=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2-custom-errors/article.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/1-js/08-error-handling/2-custom-errors/article.md b/1-js/08-error-handling/2-custom-errors/article.md index 8ea27fb40e..e4e458f753 100644 --- a/1-js/08-error-handling/2-custom-errors/article.md +++ b/1-js/08-error-handling/2-custom-errors/article.md @@ -2,7 +2,7 @@ 当我们在进行开发的时候,通常需要属于我们自己的错误类来反映任务中可能出现的特殊情况。对于网络操作错误,我们需要 `HttpError`,对于数据库操作错误,我们需要 `DbError`,对于搜索操作错误,我们需要 `NotFoundError`,等等。 -我们自定义的错误应该具有基本的错误属性,例如 `message`,`name` 以及更加详细的 `stack`。但是它们也会有属于自己的属性。举个例子,`HttpError`对象会有一个 `statusCode` 属性,取值可能为 `404`、`403` 或 `500` 等。 +我们自定义的错误应该具有基本的错误属性,例如 `message`,`name` 以及更加详细的 `stack`。但是它们也会有属于自己的属性。举个例子,`HttpError` 对象会有一个 `statusCode` 属性,取值可能为 `404`、`403` 或 `500` 等。 JavaScript 允许我们在使用 `throw` 时带任何参数,所以从技术层面上说,我们自定义的错误不需要继承 `Error` 类,但如果我们继承了这个类,就能使用 `obj instanceof Error` 来鉴别错误对象,所以我们最好继承它。 @@ -25,7 +25,7 @@ let json = `{ "name": "John", "age": 30 }`; 我们的 `ValidationError` 类应该继承自内置的 `Error` 类。 - `Error` 类是内置的,但是我们需要看一下大致的代码,来理解我们需要扩展什么。 +`Error` 类是内置的,但是我们需要看一下大致的代码,来理解我们需要扩展什么。 代码如下: @@ -124,13 +124,13 @@ try { // ... ``` -使用 `instanceof` 的做法会好很多,因为我们在以后会扩展 `ValidationError`,创造一个它的子类型,例如 `PropertyRequiredError`。而 `instanceof` 对于新的继承类也适用。所以这是个长远的保证。 +使用 `instanceof` 的做法会好很多,因为我们在以后会扩展 `ValidationError`,创造一个它的子类型,例如 `PropertyRequiredError`。而 `instanceof` 对于新的继承类也适用。所以这是个长远的保证。 还有一点很重要,在 `catch` 语句捕捉到未知的错误时,它会在抛出行 `(**)` 处重新抛出,`catch` 语句仅仅知道如何处理验证和语法错误,而其他错误(代码中的打印错误等)不应该被捕获。 ## 更进一步的继承 - `ValidationError` 类是十分通用的。因此可能会在某些方面出错。属性可能缺失,格式可能发生错误(例如 `age` 属性的值为一个字符串)。让我们来创造一个更加具体的类 `PropertyRequiredError`,为属性缺失的错误而量身定做的。它将会承载属性缺失的相关信息。 +`ValidationError` 类是十分通用的。因此可能会在某些方面出错。属性可能缺失,格式可能发生错误(例如 `age` 属性的值为一个字符串)。让我们来创造一个更加具体的类 `PropertyRequiredError`,为属性缺失的错误而量身定做的。它将会承载属性缺失的相关信息。 ```js run class ValidationError extends Error { @@ -164,7 +164,7 @@ function readUser(json) { return user; } -// try..catch实例 +// try..catch 实例 try { let user = readUser('{ "age": 25 }'); @@ -172,7 +172,7 @@ try { if (err instanceof ValidationError) { *!* alert("Invalid data: " + err.message); // 无效的数据:缺失属性:name - alert(err.name); // 必有属性错误 + alert(err.name); // PropertyRequiredError alert(err.property); // name */!* } else if (err instanceof SyntaxError) { @@ -211,7 +211,7 @@ class PropertyRequiredError extends ValidationError { } // name is correct -alert( new PropertyRequiredError("field").name ); // 必有属性错误 +alert( new PropertyRequiredError("field").name ); // PropertyRequiredError ``` 现在的自定义错误更加的简洁,特别是 `ValidationError`,我们在其构造器中删除了 `"this.name = ..."` 这一行。 @@ -285,7 +285,7 @@ try { if (e instanceof ReadError) { *!* alert(e); - // 原错误:语法错误:在位置1处不应有 b + // 原错误:语法错误:在位置 1 处不应有 b alert("Original error: " + e.cause); */!* } else { @@ -294,7 +294,7 @@ try { } ``` -上述代码中, `readUser` 正如描述的一样正常工作 —— 捕获语法以及验证的异常并且抛出 `ReadError` 异常用来代替之前的行为(未知的异常依旧重新抛出)。 +上述代码中,`readUser` 正如描述的一样正常工作 —— 捕获语法以及验证的异常并且抛出 `ReadError` 异常用来代替之前的行为(未知的异常依旧重新抛出)。 所以外部代码负责检测 `instanceof ReadError`,不必列出所有可能的异常类型。