diff --git a/docs/function.md b/docs/function.md index e800206..beaa2ac 100644 --- a/docs/function.md +++ b/docs/function.md @@ -1329,41 +1329,3 @@ clownsEverywhere( 这样的规定也使得,函数参数与数组和对象的尾逗号规则,保持一致了。 -## catch 语句的参数 - -ES2018 [允许](https://github.com/tc39/proposal-optional-catch-binding)`try...catch`结构的`catch`语句不带有参数。这个提案跟参数有关,也放在这一章介绍。 - -传统的写法是`catch`语句必须带有参数,用来接收`try`代码块抛出的错误。 - -```javascript -try { - // ··· -} catch (error) { - // ··· -} -``` - -上面代码中,即使没有用到`error`,传统写法也是不允许省略。 - -新的写法允许省略`catch`后面的参数,而不报错。 - -```javascript -try { - // ··· -} catch { - // ··· -} -``` - -新写法只在不需要错误实例的情况下有用,因此不及传统写法的用途广。 - -```javascript -let jsonData; -try { - jsonData = JSON.parse(str); -} catch { - jsonData = DEFAULT_DATA; -} -``` - -上面代码中,`JSON.parse`报错只有一种可能:解析失败。所以一旦报错,基本上不需要用到错误实例,所以可以省略`catch`后面的参数。 diff --git a/docs/let.md b/docs/let.md index a18adaa..1120229 100644 --- a/docs/let.md +++ b/docs/let.md @@ -435,30 +435,6 @@ if (true) function f() {} ``` -### do 表达式 - -本质上,块级作用域是一个语句,将多个操作封装在一起,没有返回值。 - -```javascript -{ - let t = f(); - t = t * t + 1; -} -``` - -上面代码中,块级作用域将两个语句封装在一起。但是,在块级作用域以外,没有办法得到`t`的值,因为块级作用域不返回值,除非`t`是全局变量。 - -现在有一个[提案](http://wiki.ecmascript.org/doku.php?id=strawman:do_expressions),使得块级作用域可以变为表达式,也就是说可以返回值,办法就是在块级作用域之前加上`do`,使它变为`do`表达式,然后就会返回内部最后执行的表达式的值。 - -```javascript -let x = do { - let t = f(); - t * t + 1; -}; -``` - -上面代码中,变量`x`会得到整个块级作用域的返回值(`t * t + 1`)。 - ## const 命令 ### 基本用法 diff --git a/docs/proposals.md b/docs/proposals.md new file mode 100644 index 0000000..e4e479f --- /dev/null +++ b/docs/proposals.md @@ -0,0 +1,119 @@ +# 最新提案 + +本章介绍一些尚未进入标准、但很有希望的最新提案。 + +## do 表达式 + +本质上,块级作用域是一个语句,将多个操作封装在一起,没有返回值。 + +```javascript +{ + let t = f(); + t = t * t + 1; +} +``` + +上面代码中,块级作用域将两个语句封装在一起。但是,在块级作用域以外,没有办法得到`t`的值,因为块级作用域不返回值,除非`t`是全局变量。 + +现在有一个[提案](https://github.com/tc39/proposal-do-expressions),使得块级作用域可以变为表达式,也就是说可以返回值,办法就是在块级作用域之前加上`do`,使它变为`do`表达式,然后就会返回内部最后执行的表达式的值。 + +```javascript +let x = do { + let t = f(); + t * t + 1; +}; +``` + +上面代码中,变量`x`会得到整个块级作用域的返回值(`t * t + 1`)。 + +`do`表达式的逻辑非常简单:封装的是什么,就会返回什么。 + +```javascript +// 等同于 <表达式> +do { <表达式>; } + +// 等同于 <语句> +do { <语句> } +``` + +`do`表达式的好处是可以封装多个语句,让程序更加模块化,就像乐高积木那样一块块拼装起来。 + +```javascript +let x = do { + if (foo()) { f() } + else if (bar()) { g() } + else { h() } +}; +``` + +上面代码的本质,就是根据函数`foo`的执行结果,调用不同的函数,将返回结果赋给变量`x`。使用`do`表达式,就将这个操作的意图表达得非常简洁清晰。而且,`do`块级作用域提供了单独的作用域,内部操作可以与全局作用域隔绝。 + +值得一提的是,`do`表达式在 JSX 语法中非常好用。 + +```javascript +return ( + +) +``` + +上面代码中,如果不用`do`表达式,就只能用三元判断运算符(`?:`)。那样的话,一旦判断逻辑复杂,代码就会变得很不易读。 + +## throw 表达式 + +JavaScript 语法规定`throw`是一个命令,用来抛出错误,不能用于表达式之中。 + +```javascript +// 报错 +console.log(throw new Error()); +``` + +上面代码中,`console.log`的参数必须是一个表达式,如果是一个`throw`语句就会报错。 + +现在有一个[提案](https://github.com/tc39/proposal-throw-expressions),允许`throw`用于表达式。 + +```javascript +// 参数的默认值 +function save(filename = throw new TypeError("Argument required")) { +} + +// 箭头函数的返回值 +lint(ast, { + with: () => throw new Error("avoid using 'with' statements.") +}); + +// 条件表达式 +function getEncoder(encoding) { + const encoder = encoding === "utf8" ? + new UTF8Encoder() : + encoding === "utf16le" ? + new UTF16Encoder(false) : + encoding === "utf16be" ? + new UTF16Encoder(true) : + throw new Error("Unsupported encoding"); +} + +// 逻辑表达式 +class Product { + get id() { + return this._id; + } + set id(value) { + this._id = value || throw new Error("Invalid value"); + } +} +``` + +上面代码中,`throw`都出现在表达式里面。 + +语法上,`throw`表达式里面的`throw`不再是一个命令,而是一个运算符。为了避免与`throw`命令混淆,规定`throw`出现在行首,一律解释为`throw`语句,而不是`throw`表达式。 diff --git a/sidebar.md b/sidebar.md index 55a86c1..da5e699 100644 --- a/sidebar.md +++ b/sidebar.md @@ -32,6 +32,7 @@ 1. [编程风格](#docs/style) 1. [读懂规格](#docs/spec) 1. [ArrayBuffer](#docs/arraybuffer) +1. [最新提案](#docs/proposals) 1. [参考链接](#docs/reference) ## 其他