do 表达式

本质上,块级作用域是一个语句,将多个操作封装在一起,没有返回值。

  1. {
  2. let t = f();
  3. t = t * t + 1;
  4. }

上面代码中,块级作用域将两个语句封装在一起。但是,在块级作用域以外,没有办法得到t的值,因为块级作用域不返回值,除非t是全局变量。

现在有一个提案,使得块级作用域可以变为表达式,也就是说可以返回值,办法就是在块级作用域之前加上do,使它变为do表达式,然后就会返回内部最后执行的表达式的值。

  1. let x = do {
  2. let t = f();
  3. t * t + 1;
  4. };

上面代码中,变量x会得到整个块级作用域的返回值(t * t + 1)。

do表达式的逻辑非常简单:封装的是什么,就会返回什么。

  1. // 等同于 <表达式>
  2. do { <表达式>; }
  3. // 等同于 <语句>
  4. do { <语句> }

do表达式的好处是可以封装多个语句,让程序更加模块化,就像乐高积木那样一块块拼装起来。

  1. let x = do {
  2. if (foo()) { f() }
  3. else if (bar()) { g() }
  4. else { h() }
  5. };

上面代码的本质,就是根据函数foo的执行结果,调用不同的函数,将返回结果赋给变量x。使用do表达式,就将这个操作的意图表达得非常简洁清晰。而且,do块级作用域提供了单独的作用域,内部操作可以与全局作用域隔绝。

值得一提的是,do表达式在 JSX 语法中非常好用。

  1. return (
  2. <nav>
  3. <Home />
  4. {
  5. do {
  6. if (loggedIn) {
  7. <LogoutButton />
  8. } else {
  9. <LoginButton />
  10. }
  11. }
  12. }
  13. </nav>
  14. )

上面代码中,如果不用do表达式,就只能用三元判断运算符(?:)。那样的话,一旦判断逻辑复杂,代码就会变得很不易读。