From f86d238fa4b52adbe2e1aaea50bcba779bb635a7 Mon Sep 17 00:00:00 2001 From: Hank Date: Wed, 6 Jun 2018 12:20:00 +0800 Subject: [PATCH 01/21] 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/21] 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/21] 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/21] 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/21] =?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/21] =?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/21] =?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/21] =?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/21] 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/21] =?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/21] =?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/21] =?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/21] =?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/21] =?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/21] =?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/21] =?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/21] =?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/21] =?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`,不必列出所有可能的异常类型。 From c0f200438ee3e8ed03689ee9c903e009fe719082 Mon Sep 17 00:00:00 2001 From: Hank Date: Sun, 19 Aug 2018 16:26:17 +0800 Subject: [PATCH 19/21] =?UTF-8?q?=E8=B4=A1=E7=8C=AE=E8=80=85.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contributors.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/contributors.md b/contributors.md index c6b26c997f..f20a37185b 100644 --- a/contributors.md +++ b/contributors.md @@ -1,13 +1,13 @@ -The file lists people who made significant contributions to the project: +该文件列出了对本项目做出重大贡献的人员:
    -
  • Alexey Maximov @amaxcz (admin)
  • -
  • Alexey Shisterov (tutorial)
  • -
  • Anton Vernogor @smmurf (markup)
  • -
  • Artem Beztsenny @bezart (design)
  • -
  • Ilya Kantor @iliakan (tutorial, code)
  • -
  • Yuri Tkachenko @tyv (markup)
  • +
  • Alexey Maximov @amaxcz (管理员)
  • +
  • Alexey Shisterov (教程编写)
  • +
  • Anton Vernogor @smmurf (标记)
  • +
  • Artem Beztsenny @bezart (设计)
  • +
  • Ilya Kantor @iliakan (教程、代码编写)
  • +
  • Yuri Tkachenko @tyv (标记)
-The project exists for a long time, I might have missed someone. If you expect to find yourself in the list, but you're not -- please mail me at mk@javascript.ru. +此项目存在了很长时间,我可能遗漏了一些人员。如果你本来希望在列表中发现你的名字却没有 —— 请电邮至 mk@javascript.ru From 4e18520ec480dbf113ecae32a48c29d79fc253cc Mon Sep 17 00:00:00 2001 From: Hank Date: Sun, 19 Aug 2018 16:54:50 +0800 Subject: [PATCH 20/21] =?UTF-8?q?=E8=AE=B8=E5=8F=AF=E8=AF=81.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LICENSE.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/LICENSE.md b/LICENSE.md index 60f06924e2..a2600d3d7d 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,14 +1,14 @@ -# Attribution-NonCommercial-ShareAlike 4.0 +# 署名 - 非商业性使用 - 相同方式共享 4.0 -The full license text is at . +完整的许可证文本位于 。 -You are free to: -- **Share** – copy and redistribute the tutorial in any medium or material. -- **Adapt** – remix, transform, and build upon the material. +你可以: +- **分享** —— 在任何媒体或材料中复制并扩散这些教程。 +- **合作** —— 在材料上进行重新编写或进行修改。 +- +根据以下条款: -Under the following terms: - -- **Attribution** — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. -- **NonCommercial** — You may not use the material for commercial purposes. -- **ShareAlike** — If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original. +- **署名** —— 你必须提供适当的信用担保,提供许可证的链接,并表明是否进行了更改。你可以以任何合理的方式这么做,但这不代表许可证所有者认可你或你的行为。 +- **非商业化** —— 你不能将材料用于商业用途。 +- **相同方式共享** —— 如果你在材料上进行重新编写或进行修改,你必须对你的贡献使用与原来相同的许可证。 From 853e189bb9631666ee2fa454fcf200d30abfbd63 Mon Sep 17 00:00:00 2001 From: Hank Date: Sun, 19 Aug 2018 22:56:13 +0800 Subject: [PATCH 21/21] README.md --- README.md | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 6494e18eda..9ed7c78605 100755 --- a/README.md +++ b/README.md @@ -1,36 +1,36 @@ -# The JavaScript Tutorial +# JavaScript教程 -This repository hosts the content of the Modern JavaScript Tutorial, published at [https://javascript.info](https://javascript.info). +这个仓库托管现代 JavaScript 教程的内容,发布于 [https://javascript.info](https://javascript.info)。 -## Translations +## 翻译 -Published: -- Russian: [https://github.com/iliakan/javascript-tutorial-ru](https://github.com/iliakan/javascript-tutorial-ru). +已发布: +- 俄语版: [https://github.com/iliakan/javascript-tutorial-ru](https://github.com/iliakan/javascript-tutorial-ru). -In progress: -- Chinese: the ongoing translation at [https://github.com/iliakan/javascript-tutorial-cn](https://github.com/iliakan/javascript-tutorial-cn), go ahead and join if you know Chinese. -- Spanish: https://github.com/lmauromb/javascript-tutorial-es -- German: https://github.com/MartinEls/javascript-tutorial-de +进行中: +- 中文版: 在 [https://github.com/iliakan/javascript-tutorial-cn](https://github.com/iliakan/javascript-tutorial-cn) 进行翻译,如果你懂中文,欢迎加入。 +- 西班牙语版: https://github.com/lmauromb/javascript-tutorial-es +- 德语版: https://github.com/MartinEls/javascript-tutorial-de -If you'd like to translate it into your language then fork the English tutorial and go ahead. I can publish the translation with your credits on a domain like fr.javascript.info or you can do it on your domain. +如果你想将它翻译至你使用的语言,就 fork 英文版教程并开始你的翻译。我能将它发布在域名 fr.javascript.info 下并署上你的名字,或由你发布在自己的域名下。 -You can also send PR for this file to indicate that there's work in progress. +你也可以对此文件发 PR 来表示工作正在进行中。 -Please note that the tutorial can run locally using . +请注意,此教程可以用 来达到本地运行的效果。 -## Structure +## 结构 -Every chapter, article or a task has its folder. +每个章节、每篇文章或每个任务都有其文件夹。 -The folder is named like `N-url`, where `N` is a number for the sorting purposes and `url` is the URL part with title of the material. +文件夹都是以 `N-url` 的方式命名,`N` 是用于分类的数字,`url` 是包含材料标题的 URL。 -The type of the material is defined by the file inside the folder: +材料的类型由文件夹内的文件来定义: - - `index.md` stands for a chapter - - `article.md` stands for an article - - `task.md` stands for a task (solution must be provided in `solution.md` file aswell) + - `index.md` 代表一个章节 + - `article.md` 代表一篇文章 + - `task.md` 代表一个任务(解答也必须出现在 `solution.md` 文件中) -Each of these files starts from the `# Main header`. +每个文件都从 `# Main header` 开始。 -Assets required for the material reside in the same folder. +材料所需要的资源需要处于同一文件夹内。