Panda Noir

JavaScript の限界を究めるブログでした。最近はいろんな分野を幅広めに書いてます。

for文と式文とできるとちょっとかっこいいテクニック

for文は奥が深くて、最適化出来る部分がたくさんあります。今回はそんな for の真価を垣間見ようという記事です。

for文の説明

for文は、 for(式文 or var文;式文;式文) 単文; という構成をとります。for内の式文( or var文 )はいずれも省略可能です。 for(式文 or var文;式文;式文) {複文} もあるのでは? と思った方もいらっしゃると思います。ブロックには 中の複文を単文にまとめる機能があります。だから、単文にまとめてOKです。

さて、ここで例えば下のようなプログラムがあったとしましょう。

for (var i = 0, res = ''; i < 5; i++ ) {
    res += 'hoge';
    if (i % 2 === 0) res += 'fuga';
}

このプログラムは、実は式文、ブロックそして演算子の知識があるとワンライナーにできます。

手順としては

  1. ifを消す
  2. 式文をまとめて単文にする
  3. 不要となったブロックを消す
  4. 式文をfor内に組み込む

という順です。

if を消す

まず、if を消します。 &&演算子を使えば、 if (i % 2 === 0) res += ‘fuga’; は i % 2 === 0 && (res += ‘fuga’); という式文に変換できます( res += ‘fuga’ に かっこ がついているのは、+= よりも && の方が演算子としての優先順位が高いからです)。

for (var i = 0, res = ''; i < 5; i++ ) {
    res += 'hoge';
    i % 2 === 0 && (res += 'fuga');
}

式文を単文にまとめる

さて、これでブロックの中は if文 が消えたため 式文 のみとなりました。式文 はコンマ演算子を使えば1つにまとめることが可能です。これでブロック内が式文の単文となりました。ブロック内が単文なのでブロックを外してしまいましょう。

for (var i = 0, res = ''; i < 5; i++ )
    res += 'hoge', i % 2 === 0 && (res += 'fuga');

単文をfor文内に組み込む

さて、ここで更にfor文は for(式文 or var文;式文;式文) 単文; ということを利用しましょう。forの次の単文も、forのカッコ内の最後の式文も実行タイミングは同じです。そして今、2つとも式文です。つまりまとめてしまうことができます。ただし、 単文を式文の前 に組み込んでください。通常の JavaScript のプログラムを思い出してみてください。単文が式文より前に評価されていますよね。

単文を式文にまとめる時、気をつけてほしいのが for文は 必ず 単文をとる、ということです。今 単文を中に組み込むので 単文 が消えてしまいます。そこで、for文の後にセミコロンをくっつけてください。このセミコロンは空文を作ります。そしてこの空文が for文 後ろの単文になってくれるので文法的な問題がすべて解決できます。

完成

さて、完成したコードがこちらです。

for (var i = 0, res = ''; i < 5; res += 'hoge', i % 2 === 0 && (res += 'fuga'), i++);

終わりに

実はこの記事は演算子ノ全テの補足記事です。当初は 演算子ノ全テ のおまけに入れようかと思ってたのですが、想定していたより文量が増えたので単独記事にしました。

おまけ FizzBuzz挑戦してみた

オーソドックスに組んだFizzBuzzを上記のテクニックを駆使して落としこんでみました。圧縮前と圧縮後並べておきますね。

for(i=0;i<100;i++){
    if(i%15===0){
        console.log('FizzBuzz');
    }else if(i%5===0){
        console.log('Buzz');
    }else if(i%3===0){
        console.log('Fizz');
    }else{
        console.log(i);
    }
}
for(i=0;i<100;console.log(i%15?i%5?i%3?i:'Fizz':'Buzz':'FizzBuzz'),i++);