diff --git a/files/zh-cn/web/javascript/guide/control_flow_and_error_handling/index.md b/files/zh-cn/web/javascript/guide/control_flow_and_error_handling/index.md index a914c03112705c..33a01c4051ad0f 100644 --- a/files/zh-cn/web/javascript/guide/control_flow_and_error_handling/index.md +++ b/files/zh-cn/web/javascript/guide/control_flow_and_error_handling/index.md @@ -1,35 +1,34 @@ --- -title: 流程控制与错误处理 +title: 控制流与错误处理 slug: Web/JavaScript/Guide/Control_flow_and_error_handling +l10n: + sourceCommit: f0d7ee3bc3a398612c75063fe227a5dcc515f40b --- {{jsSidebar("JavaScript Guide")}}{{PreviousNext("Web/JavaScript/Guide/Grammar_and_Types", "Web/JavaScript/Guide/Loops_and_iteration")}} -JavaScript 提供一套灵活的语句集,特别是控制流语句,你可以用它在你的应用程序中实现大量的交互性功能。本章节我们将带来关于 JavaScript 语句的一些概览。 +JavaScript 支持一套小巧的语句,特别是控制流语句,你可以用它在你的应用程序中实现大量的交互性功能。本章将对这些语句进行概览。 -这一章中的语句,在 [JavaScript 参考](/zh-CN/docs/Web/JavaScript/Reference/Statements) 中包含更为详尽的细节。在 JavaScript 代码中,分号(;)字符被用来分割语句。 +在本章中涉及的语句,[JavaScript 参考](/zh-CN/docs/Web/JavaScript/Reference/Statements)包含更为详尽的细节。在 JavaScript 代码中,分号(`;`)字符被用来分割语句。 -在 JavaScript 中,任何表达式 (expression) 都可以看作一条语句 (statement),如果你想了解表达式的详细信息,可以阅读[表达式与运算符(Expressions and operators)](/zh-CN/docs/Web/JavaScript/Guide/Expressions_and_operators)这一章节。 +JavaScript 表达式也是语句。想要了解有关表达式的完整信息,参见[表达式与运算符](/zh-CN/docs/Web/JavaScript/Guide/Expressions_and_operators)。 -## 语句块 +## 块语句 -最基本的语句是用于组合语句的语句块。该块由一对大括号界定: +最基本的语句是用于组合语句的*块语句*。块由一对花括号界定: -```plain +```js { - statement_1; - statement_2; - statement_3; - . - . - . - statement_n; + statement1; + statement2; + // … + statementN; } ``` ### 示例 -语句块通常用于流程控制,如`if`,`for`,`while`等等。 +块语句通常用于控制流语句(`if`、`for`、`while`)。 ```js while (x < 10) { @@ -37,87 +36,88 @@ while (x < 10) { } ``` -这里`{ x++; }`就是语句块。 - -**重要**:在 ECMAScript 6 标准之前,Javascript 没有块作用域。在一个块中引入的变量的作用域是包含函数或脚本,并且设置它们的效果会延续到块之外。换句话说,块语句不定义范围。JavaScript 中的“独立”块会产生与 C 或 Java 中完全不同的结果。示例: +这里,`{ x++; }` 就是块语句。 -```js -var x = 1; -{ - var x = 2; -} -alert(x); // 输出的结果为 2 -``` - -这段代码的输出是**2**,这是因为块级作用域中的 var x 变量声明与之前的声明在同一个作用域内。在 C 语言或是 Java 语言中,同样的代码输出的结果是 1。 +> [!NOTE] +> 用 [`var`](/zh-CN/docs/Web/JavaScript/Reference/Statements/var) 声明的变量不是块级作用域的,而是函数作用域或脚本作用域的,且设置它们的效果会超越到块本身之外。例如: +> +> ```js +> var x = 1; +> { +> var x = 2; +> } +> console.log(x); // 2 +> ``` +> +> 会输出 `2`,因为块中 `var x` 语句和块前面的 `var x` 语句的作用域是一样的。(在 C 或 Java 中,等效的代码会输出 `1`。) +> +> 使用 {{jsxref("Statements/let", "let")}} 或 {{jsxref("Statements/const", "const")}} 会消除这个作用域效果。 -从 ECMAScript 2015 开始,使用 `let` 和`const`变量是块作用域的。更多信息请参考 {{jsxref("Statements/let", "let")}} 和 {{jsxref("Statements/const", "const")}}。 +## 条件语句 -## 条件判断语句 +条件语句是一组会在指定的条件为真时执行的指令。JavaScript 支持两种条件语句:`if...else` 和 `switch`。 -条件判断语句指的是根据指定的条件所返回的结果(真或假或其他预定义的),来执行特定的语句。JavaScript 支持两种条件判断语句:`if...else`和`switch`。 +### if...else 语句 -### `if...else` 语句 +使用 `if` 语句在逻辑条件为 `true` 时执行语句。使用可选的 `else` 子句在条件为 `false` 时执行语句。 -当一个逻辑条件为真,用 if 语句执行一个语句。当这个条件为假,使用可选择的 else 从句来执行这个语句。if 语句如下所示: +`if` 语句看起来像这样: ```js if (condition) { - statement_1; + statement1; } else { - statement_2; -} //推荐使用严格的语句块模式,语句 else 可选 + statement2; +} ``` -条件可以是任何返回结果被计算为 true 或 false 的表达式。如果条件表达式返回的是 true,statement_1 语句会被执行;否则,statement_2 被执行。statement_1 和 statement_2 可以是任何语句,甚至你可以将另一个 if 语句嵌套其中。 +这里,`condition` 可以是任何能求值为 `true` 或 `false` 的表达式。(想要了解求值为 `true` 和 `false` 的解释,参见[布尔值](/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Boolean#描述)。) -你也可以组合语句通过使用 `else if` 来测试连续多种条件判断,就像下面一样: +如果 `condition` 求值为 `true`,执行 `statement1`。否则,执行 `statement2`。`statement1` 和 `statement2` 可以是任何的语句,包括继续嵌套的 `if` 语句。 + +你也可以使用 `else if` 组合语句按顺序测试多个条件,就像下面一样: ```js -if (condition_1) { - statement_1; -} else if (condition_2) { - statement_2; -} else if (condition_n_1) { - statement_n; +if (condition1) { + statement1; +} else if (condition2) { + statement2; +} else if (conditionN) { + statementN; } else { - statement_last; + statementLast; } ``` -要执行多个语句,可以使用语句块 ({ ... }) 来分组这些语句。通常,总是使用语句块是一个好的习惯,特别是在代码涉及比较多的 if 语句时: +在多个条件的情况下,只有第一个求值为 `true` 的逻辑条件才会被执行。想要执行多个语句,将其组合在一个块语句中(`{ /* … */ }`)。 + +#### 最佳实践 + +一般而言,总是使用块语句是最佳实践——*特别是*嵌套 `if` 语句的时候: ```js -if (条件) { - 当条件为真的时候,执行语句 1; - 当条件为真的时候,执行语句 2; +if (condition) { + // condition 为真时的语句 + // … } else { - 当条件为假的时候,执行语句 3; - 当条件为假的时候,执行语句 4; + // condition 为假时的语句 + // … } ``` -不建议在条件表达式中使用赋值语句,因为在快速查阅代码时容易把它看成等值比较。例如,不要使用下面的代码: +一般而言,最好不要将赋值(例如,`x = y`)作为 `if...else` 的条件: -> [!WARNING] -> -> ```js-nolint -> if (x = y) { -> /* 语句 */ -> } -> ``` - -如果你需要在条件表达式中使用赋值,通常在赋值语句前后额外添加一对括号。例如: - -```js-nolint -if ((x = y)) { - /* statements here */ +```js-nolint example-bad +if (x = y) { + // 在这里添加语句 } ``` -#### 错误的值 +然而,在极少数情况下,你会发现自己想要这么做,[`while`](/zh-CN/docs/Web/JavaScript/Reference/Statements/while) 文档中的[使用赋值作为条件](/zh-CN/docs/Web/JavaScript/Reference/Statements/while#使用赋值作为条件)小节是你应该了解并遵循的通用的最佳实践语法指南。 + +#### 假值 -下面这些值将被计算出 false (also known as {{Glossary("Falsy")}} values): +下面这些值求值为 `false`(也叫做[假](/zh-CN/docs/Glossary/Falsy)值): - `false` - `undefined` @@ -126,222 +126,216 @@ if ((x = y)) { - `NaN` - 空字符串(`""`) -当传递给条件语句所有其他的值,包括所有对象会被计算为真。 +所有其他的值——包括所有的对象——在被传递给条件语句时会求值为 `true`。 -请不要混淆原始的布尔值`true`和`false` 与 {{jsxref("Boolean")}}对象的真和假。例如: - -```js -var b = new Boolean(false); -if (b) //结果视为真 -if (b == true) // 结果视为假 -``` +> [!NOTE] +> 请不要混淆原始布尔值 `true` 和 `false` 与 {{jsxref("Boolean")}} 对象的真和假! +> +> 例如: +> +> ```js +> const b = new Boolean(false); +> if (b) { +> // 这个条件求值为 true +> } +> if (b == true) { +> // 这个条件求值为 false +> } +> ``` #### 示例 -在以下示例中,如果`Text`对象中的字符数为 3,函数`checkData`将返回`true`;否则,显示警报并返回`false`。 +在下列示例中,如果 `Text` 对象中的字符数为 3,函数 `checkData` 将返回 `true`;否则,显示警告并返回 `false`。 ```js function checkData() { - if (document.form1.threeChar.value.length == 3) { + if (document.form1.threeChar.value.length === 3) { return true; } else { - alert( - "Enter exactly three characters. " + - document.form1.threeChar.value + - " is not valid.", - ); + alert(`请正好输入 3 个字符。${document.form1.threeChar.value}是无效的`); return false; } } ``` -### `switch` 语句 +### switch 语句 + +`switch` 语句允许程序求一个表达式的值并且尝试将表达式的值和 `case` 标签进行匹配。如果匹配成功,程序会执行相关的语句。 -`switch` 语句允许一个程序求一个表达式的值并且尝试去匹配表达式的值到一个 `case` 标签。如果匹配成功,这个程序执行相关的语句。`switch` 语句如下所示: +`switch` 语句看起来像这样: ```js switch (expression) { - case label_1: - statements_1 - [break;] - case label_2: - statements_2 - [break;] - ... - default: - statements_def - [break;] + case label1: + statements1; + break; + case label2: + statements2; + break; + // … + default: + statementsDefault; } ``` -程序首先查找一个与 `expression` 匹配的 `case` 语句,然后将控制权转移到该子句,执行相关的语句。如果没有匹配值,程序会去找 `default` 语句,如果找到了,控制权转移到该子句,执行相关的语句。如果没有找到 `default`,程序会继续执行 `switch` 语句后面的语句。`default` 语句通常出现在 switch 语句里的最后面,当然这不是必须的。 +JavaScript 求值上面的 switch 语句的过程如下: -`可选的 break` 语句与每个 `case` 语句相关联,保证在匹配的语句被执行后程序可以跳出 `switch` 并且继续执行 `switch` 后面的语句。如果 break 被忽略,则程序将继续执行 switch 语句中的下一条语句。 +- 程序首先查找一个与 expression 的值匹配的 `case` 子句标签,然后将控制权转移到该子句,执行相关的语句。 +- 如果没有匹配的标签,程序会去找可选的 `default` 子句: + - 如果找到了 `default` 子句,程序会将控制权转移到该子句,执行相关的语句。 + - 如果没有找到 `default` 子句,程序会继续执行 `switch` 语句后面的语句。 + - (`default` 子句通常是最后一个子句,当然这不是必须的。) -**示例** -在如下示例中,如果 `fruittype` 等于 "Bananas", 程序匹配到对应 "Bananas" 的`case` 语句,并执行相关语句。当执行到 `break` 时,程序结束了 `switch` 并执行 `switch` 后面的语句。如果不写 `break` ,那么程序将会执行 `case "Cherries"` 下的语句。 +#### break 语句 + +每个 `case` 子句会关联一个可选的 `break` 语句,它能保证在匹配的语句被执行后程序可以跳出 `switch` 并且继续执行 `switch` 后面的语句。如果 `break` 被忽略,程序会在 `switch` 语句内继续执行(将会执行下一个 `case` 的语句,依此类推)。 + +#### 示例 + +在下列示例中,如果 `fruitType` 等于 `"Bananas"`,程序将该值与 `case "Bananas"` 匹配,并执行相关语句。当执行到 `break` 时,程序结束 `switch` 并执行 `switch` 后面的语句。如果不写 `break` ,那么程序将会执行 `case "Cherries"` 下的语句。 ```js -switch (fruittype) { +switch (fruitType) { case "Oranges": - document.write("Oranges are $0.59 a pound.
"); + console.log("橙子是 $0.59 一磅"); break; case "Apples": - document.write("Apples are $0.32 a pound.
"); + console.log("苹果是 $0.32 一磅"); break; case "Bananas": - document.write("Bananas are $0.48 a pound.
"); + console.log("香蕉是 $0.48 一磅"); break; case "Cherries": - document.write("Cherries are $3.00 a pound.
"); + console.log("樱桃是 $3.00 一磅"); break; case "Mangoes": + console.log("芒果是 $0.56 一磅。"); + break; case "Papayas": - document.write("Mangoes and papayas are $2.79 a pound.
"); + console.log("木瓜是 $2.79 一磅。"); break; default: - document.write("Sorry, we are out of " + fruittype + ".
"); + console.log(`对不起,${fruitType} 卖完了。`); } -document.write("Is there anything else you'd like?
"); +console.log("还有其他什么是你喜欢的吗?"); ``` ## 异常处理语句 -你可以用 `throw` 语句抛出一个异常并且用 `try...catch` 语句捕获处理它。 +你可以用 `throw` 语句抛出一个异常并且用 `try...catch` 语句处理它。 -- [`throw`](/zh-CN/docs/Web/JavaScript/Guide/Control_flow_and_error_handling#throw_statement)语句 -- [`try...catch`](/zh-CN/docs/Web/JavaScript/Guide/Control_flow_and_error_handling#try...catch_statement)语句 +- [`throw` 语句](#throw_语句) +- [`try...catch` 语句](#try...catch_语句) ### 异常类型 -JavaScript 可以抛出任意对象。然而,不是所有对象能产生相同的结果。尽管抛出数值或者字母串作为错误信息十分常见,但是通常用下列其中一种异常类型来创建目标更为高效: +JavaScript 可以抛出任意对象。然而,并非所有抛出的对象都是生而平等的。尽管抛出数字或者字符串作为错误信息十分常见,但是用下列其中一种专门为这个目的而创建的异常类型通常更为高效: -- [ECMAScript exceptions](/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Error#Error_types) -- {{domxref("DOMException")}} and {{domxref("DOMError")}} +- [ECMAScript 异常](/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Error#错误类型) +- [`DOMException`](/zh-CN/docs/Web/API/DOMException) -### `throw` 语句 +### throw 语句 -使用`throw`语句抛出一个异常。当你抛出异常,你规定一个含有值的表达式要被抛出。 +使用 `throw` 语句抛出异常。`throw` 语句会指明要抛出的值: ```js throw expression; ``` -你可以抛出任意表达式而不是特定一种类型的表达式。下面的代码抛出了几个不同类型的表达式: +你可以抛出任意表达式而不是特定类型的表达式。下面的代码抛出了几个不同类型的异常: ```js -throw "Error2"; // String type -throw 42; // Number type -throw true; // Boolean type +throw "错误 2"; // 字符串类型 +throw 42; // 数字类型 +throw true; // 布尔类型 throw { - toString: function () { - return "I'm an object!"; + toString() { + return "我是一个对象"; }, }; ``` -> [!NOTE] -> 你可以在抛出异常时声明一个对象。那你就可以在 catch 块中查询到对象的属性。 +### try...catch 语句 -```js -// Create an object type UserException -function UserException(message) { - this.message = message; - this.name = "UserException"; -} - -// Make the exception convert to a pretty string when used as -// a string (e.g. by the error console) -UserException.prototype.toString = function () { - return this.name + ': "' + this.message + '"'; -}; +`try...catch` 语句用于标记一段要尝试的语句块,并指定抛出异常时的一个或多个响应。如果抛出了异常,`try...catch` 语句会捕获它。 -// Create an instance of the object type and throw it -throw new UserException("Value too high"); -``` - -### `try...catch` 语句 +`try...catch` 语句由 `try` 块(其包含一个或多个语句)和 `catch` 块(其包含在 `try` 块中抛出异常时要执行的语句)组成。 -`try...catch` 语句标记一块待尝试的语句,并规定一个以上的响应应该有一个异常被抛出。如果我们抛出一个异常,`try...catch`语句就捕获它。 +换句话说,你希望 `try` 块执行成功——但如果它没有执行成功,那么你希望将控制转移到 `catch` 块。如果 `try` 块中的语句(或者在 `try` 块中调用的函数里)抛出了异常,那么控制*立马*转移到 `catch` 块。如果 `try` 块没有抛出异常,`catch` 块就会被跳过。`finally` 块总会紧跟在 `try` 和 `catch` 块之后执行,但会在 `try...catch` 语句后面的语句之前执行。 -`try...catch` 语句有一个包含一条或者多条语句的 try 代码块,0 个或 1 个的`catch`代码块,catch 代码块中的语句会在 try 代码块中抛出异常时执行。换句话说,如果你在 try 代码块中的代码如果没有执行成功,那么你希望将执行流程转入 catch 代码块。如果 try 代码块中的语句(或者`try` 代码块中调用的方法)一旦抛出了异常,那么执行流程会立即进入`catch` 代码块。如果 try 代码块没有抛出异常,catch 代码块就会被跳过。`finally` 代码块总会紧跟在 try 和 catch 代码块之后执行,但会在 try 和 catch 代码块之后的其他代码之前执行。 +下列示例使用了 `try...catch` 语句。示例调用的函数是根据传递的值从数组中获取一个月份名称。如果该值与月份数值(`1`-`12`)不相符,会抛出带有 `"无效的月份数值"` 值的异常,然后在 `catch` 块的语句中设 `monthName` 变量为 `"未知"`。 -下面的例子使用了`try...catch`语句。示例调用了一个函数用于从一个数组中根据传递值来获取一个月份名称。如果该值与月份数值不相符,会抛出一个带有`"InvalidMonthNo"`值的异常,然后在捕捉块语句中设`monthName`变量为`unknown`。 - -```js +```js-nolint function getMonthName(mo) { - mo = mo - 1; // Adjust month number for array index (1 = Jan, 12 = Dec) - var months = [ - "Jan", - "Feb", - "Mar", - "Apr", - "May", - "Jun", - "Jul", - "Aug", - "Sep", - "Oct", - "Nov", - "Dec", + mo--; // 将月份调整为数组索引(这样的话,0 = 一月,11 = 十二月) + const months = [ + "一月", "二月", "三月", "四月", "五月", "六月", + "七月", "八月", "九月", "十月", "十一月", "十二月", ]; if (months[mo]) { return months[mo]; } else { - throw "InvalidMonthNo"; //throw keyword is used here + throw new Error("无效的月份数值"); // 在这使用 throw 关键字 } } try { - // statements to try - monthName = getMonthName(myMonth); // function could throw exception + // 要尝试的语句 + monthName = getMonthName(myMonth); // 可能抛出异常的函数 } catch (e) { - monthName = "unknown"; - logMyErrors(e); // pass exception object to error handler -> your own function + monthName = "未知"; + logMyErrors(e); // 将异常对象传递给错误处理器(例如,你写的函数) } ``` -#### `catch` 块 +#### catch 块 -你可以使用`catch`块来处理所有可能在`try`块中产生的异常。 +你可以使用 `catch` 块来处理所有可能在 `try` 块中产生的异常。 -```js -catch (catchID) { +```js-nolint +catch (exception) { statements } ``` -捕捉块指定了一个标识符(上述语句中的`catchID`)来存放抛出语句指定的值;你可以用这个标识符来获取抛出的异常信息。在插入`throw`块时 JavaScript 创建这个标识符;标识符只存在于`catch`块的存续期间里;当`catch`块执行完成时,标识符不再可用。 +`catch` 块指定的标识符(上述语句中的 `exception`)会存储由 `throw` 语句指定的值。你可以用这个标识符来获取抛出的异常的信息。在进入 `catch` 块时 JavaScript 会创建这个标识符。标识符只存在于 `catch` 块的存续期间里。当 `catch` 块执行完成时,标识符不再可用。 -举个例子,下面代码抛出了一个异常。当异常出现时跳到`catch`块。 +举个例子,下面代码抛出了一个异常。当异常出现时控制会转移到 `catch` 块。 ```js try { - throw "myException"; // generates an exception -} catch (e) { - // statements to handle any exceptions - logMyErrors(e); // pass exception object to error handler + throw "我的异常"; // 生成一个异常 +} catch (err) { + // 处理异常的表达式 + logMyErrors(err); // 将异常对象传递给错误处理器 } ``` -#### `finally`块 +> [!NOTE] +> 在 `catch` 块中将错误输出到控制台时,建议使用 `console.error()` 而不是 `console.log()` 进行调试。它会将消息格式化为错误,并将其添加到页面生成的错误消息列表。 -`finally`块包含了在 try 和 catch 块完成后、下面接着 try...catch 的语句之前执行的语句。`finally`块无论是否抛出异常都会执行。如果抛出了一个异常,就算没有异常处理,`finally`块里的语句也会执行。 +#### finally 块 -你可以用`finally`块来令你的脚本在异常发生时优雅地退出;举个例子,你可能需要在绑定的脚本中释放资源。接下来的例子用文件处理语句打开了一个文件(服务端的 JavaScript 允许你进入文件)。如果在文件打开时一个异常抛出,`finally`块会在脚本错误之前关闭文件。 +`finally` 块包含的语句在 `try` 和 `catch` 块执行*之后*执行。此外,`finally` 块在 `try…catch…finally` 语句后面的代码*之前*执行。 + +也应该注意,`finally` 块*无论是否*抛出异常都会执行。如果抛出了一个异常,就算没有 `catch` 块处理抛出的异常,`finally` 块里的语句也会执行。 + +你可以用 `finally` 块来令你的脚本在异常发生时优雅地退出。举个例子,你可能需要释放脚本绑定的资源。 + +下列的示例打开一个文件,然后执行使用这个文件的语句。(服务器端 JavaScript 允许你访问文件。)如果在文件打开时抛出异常,`finally` 块会在脚本失败之前关闭文件。在这使用 `finally` 能*确保*文件永远不会是打开状态,即使发生了错误。 ```js openMyFile(); try { - writeMyFile(theData); //This may throw a error + writeMyFile(theData); // 这可能会抛出错误 } catch (e) { - handleError(e); // If we got a error we handle it + handleError(e); // 如果错误出现了,处理它 } finally { - closeMyFile(); // always close the resource + closeMyFile(); // 总是关闭资源 } ``` -如果`finally`块返回一个值,该值会是整个`try-catch-finally`流程的返回值,不管在`try`和`catch`块中语句返回了什么: +如果 `finally` 块返回一个值,该值会是整个 `try…catch…finally` 流程的返回值,不管在 `try` 和 `catch` 块中的 `return` 语句返回了什么: ```js function f() { @@ -350,74 +344,85 @@ function f() { throw "bogus"; } catch (e) { console.log(1); - return true; // this return statement is suspended - // until finally block has completed - console.log(2); // not reachable + // 这个 return 语句会被挂起直到 finally 块结束 + return true; + console.log(2); // 不可达 } finally { console.log(3); - return false; // overwrites the previous "return" - console.log(4); // not reachable + return false; // 覆盖前面的“return” + console.log(4); // 不可达 } - // "return false" is executed now - console.log(5); // not reachable + // 现在执行“return false” + console.log(5); // 不可达 } -f(); // console 0, 1, 3; returns false +console.log(f()); // 0、1、3、false ``` -用`finally`块覆盖返回值也适用于在`catch`块内抛出或重新抛出的异常: +用 `finally` 块覆盖返回值也适用于在 `catch` 块内抛出或重新抛出的异常: ```js function f() { try { throw "bogus"; } catch (e) { - console.log('caught inner "bogus"'); - throw e; // this throw statement is suspended until - // finally block has completed + console.log("捕获内部的“bogus”"); + // 这个 return 语句会被挂起直到 finally 块结束 + throw e; } finally { - return false; // overwrites the previous "throw" + return false; // 覆盖前面的“throw” } - // "return false" is executed now + // 现在执行“return false” } try { - f(); + console.log(f()); } catch (e) { - // this is never reached because the throw inside - // the catch is overwritten - // by the return in finally - console.log('caught outer "bogus"'); + // 这永远不会抵达! + // f() 执行时,`finally` 块返回 false,而这会覆盖上面的 `catch` 中的 `throw` + console.log("捕获外部的“bogus”"); } -// OUTPUT -// caught inner "bogus" +// 日志: +// 捕获内部的“bogus” +// false ``` #### 嵌套 try...catch 语句 -你可以嵌套一个或多个`try ... catch`语句。如果一个内部`try ... catch`语句没有`catch`块,它需要有一个`finally`块,并且封闭的`try ... catch`语句的`catch`块被检查匹配。有关更多信息,请参阅[try... catch](/zh-CN/docs/Web/JavaScript/Reference/Statements/try...catch)参考页上的[嵌套 try-blocks](/zh-CN/docs/Web/JavaScript/Reference/Statements/try...catch#Nested_try-blocks)。 +你可以嵌套一个或多个 `try ... catch` 语句。 -### 使用`Error`对象 +如果一个内部 `try` 块*没有*对应的 `catch` 块: -根据错误类型,你也许可以用'name'和'message'获取更精炼的信息。'name'提供了常规的错误类(如 'DOMException' 或 'Error'),而'message'通常提供了一条从错误对象转换成字符串的简明信息。 +1. 它*必须*有一个 `finally` 块,以及 +2. 包围的 `try...catch` 语句的 `catch` 块会被检查是否能处理该异常。 -在抛出你个人所为的异常时,为了充分利用那些属性(比如你的`catch`块不能分辨是你个人所为的异常还是系统的异常时),你可以使用 Error 构造函数。比如: +想要了解更多信息,参见 [`try... catch`](/zh-CN/docs/Web/JavaScript/Reference/Statements/try...catch) 参考页上的[嵌套 try 块](/zh-CN/docs/Web/JavaScript/Reference/Statements/try...catch#嵌套_try_块)。 + +### 使用 Error 对象 + +根据错误类型,你也许可以用 `name` 和 `message` 属性获取更精炼的信息。 + +`name` 属性提供了常规的 `Error` 类(如 `DOMException` 或 `Error`),而 `message` 通常提供的信息比将错误对象转换成字符串得到的信息更简明。 + +在抛出自定义异常时,为了充分利用那些属性(比如 `catch` 块不能分辨是自定义异常还是系统异常时),你可以使用 `Error` 构造函数。 + +比如: ```js -function doSomethingErrorProne () { +function doSomethingErrorProne() { if (ourCodeMakesAMistake()) { - throw (new Error('The message')); + throw new Error("消息"); } else { - doSomethingToGetAJavascriptError(); + doSomethingToGetAJavaScriptError(); } } -.... + try { doSomethingErrorProne(); -} -catch (e) { - console.log(e.name); // logs 'Error' - console.log(e.message); // logs 'The message' or a JavaScript error message) +} catch (e) { + // 现在,实际使用 `console.error()` + console.error(e.name); // 'Error' + console.error(e.message); // “消息”,或者一个 JavaScript 错误消息 } ``` diff --git a/files/zh-cn/web/javascript/guide/introduction/index.md b/files/zh-cn/web/javascript/guide/introduction/index.md index a235c1fd7a7799..6c505ec40941ce 100644 --- a/files/zh-cn/web/javascript/guide/introduction/index.md +++ b/files/zh-cn/web/javascript/guide/introduction/index.md @@ -5,7 +5,7 @@ l10n: sourceCommit: d71da812ee94c20658cb1916a123a42254ea545c --- -{{jsSidebar("JavaScript 指南")}} {{PreviousNext("Web/JavaScript/Guide", "Web/JavaScript/Guide/Grammar_and_types")}} +{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide", "Web/JavaScript/Guide/Grammar_and_types")}} 本章介绍了 JavaScript,并且讨论了它的一些基本概念。