カオスになりがちな三項演算子と論理演算子を使って見通しをよくしたい


こんにちは櫻井です。
昔、三項演算子と論理演算子がある程度理解できてこっちの方がすっきりしていいんじゃないか?と思って三項演算子と論理演算子を使ってJSを書いた時があったんですが、数日してそのJSを直す必要が出た時にどこからどこを比較しているのかとかがとにかくわかりづらくてデバックに大苦戦した思い出があります。それ以来、三項演算子と論理演算子を使ってきませんでしたが、使い方さえ誤らなければちゃんと見通しの良いソースができる気がしてきたので振り返りつつ使い所を考えていきたいと思います。

三項演算子

まずは三項演算子について説明していきたいと思います。
カオスの根源みたいなやつです。何度泣かされたことか。
三項演算子はif文の代わりによく使われます。if文を短くしたようなものだと思ってください。
三項演算子の構文は A?B:Cという形で使われます。if文の()の中に当たるのがAで、Aがtrueだった時の処理がB、Aがfalseだった時の処理がCです。まんまif文ですね。
なので例えば

  
    (function () {
      var x = 'hoge';
      if(x == 'hoge') {
        var y = 'fuga';
      } else {
        var y = 'hoge'
      }
    })()
  

こんなif文があったとしたら三項演算子で書くと

  
    (function () {
      var x = 'hoge';
      var y = x == 'hoge' ? 'fuga' : 'hoge';
    })()
  

if文で書いた場合も三項演算子で書いた場合もyの値は同じになります。
このくらいならまだわかりやすいですかね。
次は else if の場合をみていきましょう。

  
    (function () {
      var x = 'fuga';
      if(x == 'hoge') {
        var y = 'fuga';
      } else if (x == 'fuga'){
        var y = 'hoge';
      } else {
        var y = 'piyo'
      }
    })()
  

この場合三項演算子で書くと

  
    (function () {
      var x = 'fuga';
      var y = x == 'hoge' ? 'fuga' : x == 'fuga' ? 'hoge': 'piyo';
    })()
  

だいぶ訳わかんなくなってきました。
三項演算子を使う場合最大でもif elseまでで止めておかないとえらいことになりそうです。
if elseまででも長い処理を三項演算子で書くと見通しが悪くなりそうです。変数の値を他の変数の値次第で変えたい時とかにちょっと使うくらいがちょうどいいかもしれません。

論理演算子

論理演算子はよくif文の()の中に使われている&&や||、!のことです。
&&は論理AND演算子と呼ばれ A && B という形をとります。
if文の中でよく使われるの「AかつBの場合」という風に思いがちですが、実はそうではなくて「Aがtrueの場合はB、Aがfalseの場合はA」という形をとります。
例えば

  
    var x = 'fuga';
    var y = x && 'hoge';
  

この場合はyにhogeが入ります。

  
    var x;
    var y = x && 'hoge';
  

この場合はxは変数名だけ定義されているだけなのでfalseになります。なのでyはundefinedになります。
これを利用してAがtrueだったらBの処理を走らせるってことをするとカオスなことになっていきます。

  
    (function () {
      var target = document.querySelector('#js-txt');
      var x = 'fuga';
      var y = x && (target.innerText += x) && 'hoge';
    })()
  

この場合、#js-txtにfugaを書き込んだ後、yにhogeを入れています。JSの処理の流れをコントロールできるのはいいんですが別にこんな書き方する必要がないしより複雑になってくると一度エラーが出ると何が原因でエラーになったのか無駄にわかりづらくなります。

||は論理OR演算子と呼ばれA||Bという形をとります。
こちらは「AまたはB」と思いがちですが「Aがtrueの場合はA、Aがfalseの場合はB」という形をとります。&&の時とは逆ですね。
こちらはよくみるものだと以下のようなものがあります。

  
    (function () {
      var SCROLL_TOP = window.scrollY || window.pageYOffset;
    })()
  

スクロール量を計測するものですがwindow.scrollYが古いブラウザだとで対応していないので古いブラウザの場合はwindow.pageYOffsetでスクロール量を取得するというものです。

!は論理 NOT演算子と呼ばれ!Aという形で使われます。
これはif文で使うのと変わらず「Aでない場合」という形をとります。

カオスなJSを作らないために

これらを組合せえればif文を使わなくてもJSは書けます。書けはしますがとてつもなく見通しが悪くなります。後になって見直しした時の苦労を考えると三項演算子も論理演算子も使わないに方がいい気もします。
ですが論理OR演算子の例で上げたものはわざわざif文を使って書くよりわかりやすいしシンプルに思えます。
三項演算子と論理演算子の使い所は変数に値を入れ込む時に限り、if文で言うelse ifは使わないようにすればカオスにはならず見通しもよくなるような気がします。

Scroll to top