読者です 読者をやめる 読者になる 読者になる

JS.next

JavaScriptの最新実装情報を追うブログ

do式が実装された

概要

ブロック文のようでありながら、かつ中に書かれた最後の式の評価を返すdo式が実装された。


基本

let foo = do {    // ブロックスコープを作る
  let x = 1 + 1   // 中に文(や式)を記述できる
  x + 3           // 最後に評価された式がdo式の結果となる 
  function fn(){} // 文は評価されない
}

console.log(foo)  // 5


但しfor文やwhile文などは少し注意が必要で、
まず初期化部、条件部、更新部の評価はdo式が返す値にならない。

let bar = do {
  for (let i = 1; i <= 10; i++) i
} // 実際の最後の式評価は (11 <= 10) => false

console.log(bar)  // 10


そして処理部に何も書かれていない場合でも、undefinedと評価される。

let baz = do {
  123
  for (let i = 1; i <= 10; i++) ;
}

console.log(baz)  // undefined


利用例

ES2015: 即時関数

//......
let n = (() => {
  let n = 0
  for (let i = 1; i <= 10; i++) n += i
  return n
})()  // 55
//......


ES2017?: do式

//......
let n = do {
  let n = 0
  for (let i = 1; i <= 10; i++) n += i
}  // 55
//......


ES2015: 即時関数

let Foo = (() => {
  //......
  return class Foo {
    //......
  }
})()


ES2017?: do式

let Foo = do {
  //......
  ;(class Foo {  // 関数やクラスの宣言文は評価されないので、式として評価させる
    //......
  })
}


アロー関数と組み合わせる
ES2015:

let plus = (a, b) => {
  console.log(a, b)
  return a + b
}


ES2017?:

let plus = (a, b) => do { console.log(a, b), a + b }


switch文と組み合わせる
ES2015:

let mes
switch (true) {
         case score  <  50: mes = 'Again!'
  break; case score  < 100: mes = 'Good!'
  break; default          : mes = 'Perfect!'
}


ES2017?:

let mes = do {
  switch (true) {
           case score  <  50: 'Again!'
    break; case score  < 100: 'Good!'
    break; default          : 'Perfect!'
  }
} 


try-catch文と組み合わせる
ES2015:

let v
try {
  v = eval(hoge)
} catch(e) {
  v = e
}


ES2017:

let v = do {
  try {
    eval(hoge)
  } catch(e) { e }
}


面白いパターン

let fn = () => {
  return 'A' + do {
    return 'B' + do {
      return 'C'
    }
  }
}

fn()  // "C"


V8参考仕様

strawman:do_expressions [ES Wiki]


実装されるバージョン

V8 4.8.121