Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

  1. Home
  2. JavaScriptAdvanced - Using the Ternary (Conditional) Operator

Using the Ternary (Conditional) Operator - Japanese Only

みなさまどうも。

続きまして『三項演算子』(条件演算子)をやっていきましょう。ちょっとした分岐処理に使われる構文で、まあ基本的にはシンプルな『if文』だと思っていただいてOKです。というわけでサンプルがこちら。

true? console.log(true): console.log(false);

見慣れていないとちょっと不思議な感じがするかもしれませんが、構文自体はめっちゃ簡単です。

使用する記号は『?』と『:』で、『?』の左側の部分(上記のサンプルだと『true』の部分)に条件を書きます。

その結果が『true』扱いになるものだったら『:』の左側の処理(上記のサンプルだと『console.log(true)』の部分)が実行され、『false』扱いになるものだったら『:』の右側の処理(上記のサンプルだと『console.log(false)』の部分)が実行されます。

true? console.log(true): console.log(false); // 『?』の左側のオペランドが『true』なので『:』の左側の処理が実行されtrueと出力されます。
false? console.log(true): console.log(false); // 『?』の左側のオペランドが『false』なので『:』の右側の処理が実行されfalseと出力されます。

上記のサンプルを『if文』で書き直すとこういう感じになりますね。

// 『true? console.log(true): console.log(false);』の場合。
if(true) console.log(true);
else console.log(false);

// 『false? console.log(true): console.log(false);』の場合。
if(false) console.log(true);
else console.log(false);

記述方法はこんな感じです。ちなみに上記のサンプルには『;』が書いてありますが、これは文末に書いているいつもの『;』なので『三項演算子』との直接の関係はないのでご注意です。『三項演算子』の構文として使用される記号は『?』と『:』だけです。

あと条件を記述する部分を『()』で包む記法がありますので紹介しておきます。以下のような感じですね。以下の『()』は演算の優先順位を決める『()』なので中身に影響は与えることはありません。

(true)? console.log(true): console.log(false); // 『?』の左側のオペランドが『true』なので『:』の左側の式が実行されtrueと出力されます。
(false)? console.log(true): console.log(false); // 『?』の左側のオペランドが『false』なので『:』の右側の式が実行されfalseと出力されます。

なぜ『()』で包むのかというと『三項演算子』は条件が複雑になってくると少々読みづらくなってしまう傾向があるからです。以下のソースコードをみてみましょう。

x || (y && y.length < 5) || z === "Sun"? x.innerHTML = "商品一覧: 只今キャンペーン中です!": x.innerHTML = "商品一覧:";

このように条件が複雑になった場合だとどこまでが条件なのかちょっと分かりづらいですよね。こういうときに『()』で包んであげると『if文』の記法と近くなるため少し読みやすくなったりします。先ほどのサンプルと以下のサンプルを見比べてみて下さい。

(x || (y && y.length < 5) || z === "Sun")? x.innerHTML = "商品一覧: 只今キャンペーン中です!": x.innerHTML = "商品一覧:";

この辺は好みになるのでお好きなようにして頂いてOKで、コーディングルールなどがあればそちらに従ってしまって下さい。尚、著者は『()』で包む派ですので当サイトでは『()』で包む記法でやっていきたいと思います。

あと上記のように条件が長くなった場合は『?』と『:』あたりでちょいと改行してあげると良いかもしれません。

(x || (y && y.length < 5) || z === "Sun")?
    x.innerHTML = "商品一覧: 只今キャンペーン中です!" :
    x.innerHTML = "商品一覧:";

こうすることで少し読みやすくなったりします。まあこの辺も好みなのでお好きなように書いてしまってOKです。

続いて『三項演算子』の色々な使い道と注意点等をみていきましょう。まず変数代入などで使用されるパターンです。

var x = (Math.random() < 0.5)? "0.5未満でした。": "0.5以上でした。";

console.log(x);

※ 『Math.random()』は『1』未満の数値をランダムで返してくれる関数(メソッド)です。

変数『x』の代入処理の際に『三項演算子』が使用されていますね。『if文』を使用するよりも記述が短く済んで楽ちんなので、これが『三項演算子』の使い道で一番多いパターンかと思います。『if文』で構築した場合と見比べてみましょう。

var x;
if(Math.random() < 0.5){
    x = "0.5未満でした。";
}
else{
    x = "0.5以上でした。";
}

console.log(x);

『三項演算子』の方が大分すっきりしているのを感じていただけるかと思います。

続いて他の演算の途中で『三項演算子』が使用されるパターンです。

console.log((Math.random() < 0.5)? "0.5未満でした。": "0.5以上でした。");

上記のサンプルは『console.log()』の引数の中で『三項演算子』が使われていますね。『if文』と違い『三項演算子』は『ただの式』という扱いなので色々なところに記述することができます。例えば上記のサンプルの分岐処理を無理やり『if文』で書くと訳の分からない構文になりさくっとエラーとなります。

console.log(if(Math.random() < 0.5) "0.5未満でした。" else "0.5以上でした。"); // これはエラーです。

もし『if文』で書くならば『即時関数』などでラップしてあげないとダメです。

console.log(function(){
    if(Math.random() < 0.5) return "0.5未満でした。";
    else return "0.5以上でした。";
}());

『三項演算子』の方がささっと記述できるので楽ですね。

続いてJavaScriptの『三項演算子』は『,』で区切りつつ『()』で包んであげることで複数の式を実行(評価)することができます。以下のサンプルを見てみましょう。

(true)?
    (
        console.log("trueだよぉ..."),
        console.log("trueだってばぁ..."),
        console.log("もう何回言わせるの...恥ずかしいよぉ..."),
        console.log("バカぁ...")
    ):
    (
        console.log("falseだよぉ...")
    );

かなりカオスですが上記のサンプル、ちゃんと実行させることができます。

ちなみに『:』の両側の処理を包んでいる『()』は必須です。『()』で優先順位を決めつつ文をまとめてあげないとエラーになりますので注意です。

(true)? // これは動きません。
    console.log("trueだよぉ..."),
    console.log("trueだってばぁ..."),
    console.log("もう何回言わせるの...恥ずかしいよぉ..."),
    console.log("trueだってばぁ..."):
    console.log("falseだよぉ...");

さて、このように式が沢山あった場合の最終的な返り値(戻り値)はどれになるのでしょうか。以下のサンプルで出力されるのはどれになるのか、というお話ですね。

var x = (true)? (0, 1, 2, 3, 4, 5): (false);
console.log(x);

答えは数値『5』になります。複数の式が含まれていた場合、最後の式で評価(演算)された返り値を受け取る形になります。例えば『console.log()』は『undefined』を返すので以下のサンプルで出力されるのは『undefined』になります。

var x = (true)? (0, 1, 2, 3, 4, 5, console.log("初音ミク!!")): (false);
console.log(x);

実は『,』という演算子はそれぞれの演算対象を左側から順番に実行(評価)し、最後の結果を返す、という処理を行なう演算子だったりします。

例えば以下のサンプルを見てください。

console.log(0);
console.log(1);
console.log(2);
console.log(3);
console.log(4);

いつもの『;』を使用していますね。これの最後の『;』以外を『,』に変更してもOKだったりします。

console.log(0), // これもちゃんと実行できます。
console.log(1),
console.log(2),
console.log(3),
console.log(4);

そして引数などで受け取ることも可能です。その場合は『()』で演算の優先順位を決めつつ文をまとめてあげないとダメなので忘れないようにして下さい。

var x = (0, 1, 2, 3, 4, 5); // この『()』は必須です。
console.log(x) // 最後の結果を受け取るので数値『5』が出力されます。

さらに応用すると『for文』の条件の中で複数の式が書けちゃったりします。これ覚えておくと便利なんで是非使ってみて下さい。複数の変数をインクリメントしたいときなんかにとっても便利です。

for(var i = 0, j = 0; i < 10; ++i, ++j); // 変数『i』のついでに変数『j』もインクリメントしちゃいます。
console.log(j); // 『10』と出力されます。

というわけで先程『三項演算子』の中で複数の式を実行できるサンプルを紹介しましたが、あれはこの挙動を使用してたのでした。

ちょっとした処理を構築するとき便利なので機会があれば使ってみてください。ただし、記述がトリッキーになりがちなので使いすぎには注意です。

続いて『三項演算子』の中で『三項演算子』を使用する荒業も可能です。以下のサンプルを見てみましょう。

var x = Math.random(),
    y = (x < 0.5)?
        (x < 0.25)? "変数『x』は0.25未満でした。": "変数『x』は0.5未満かつ0.25以上でした。":
        "変数『x』は0.5以上でした。";
console.log(y);

かなり読みづらく感じる方も多いかと思います。この勢いでさらにもういっちょ複雑なやつを見てみましょう。

以下は著者が書いたシンプルなデジタル時計のプログラムです。わざと『if文』を使用しないで全ての分岐処理を『三項演算子』で書いてみました。

(function(){
    if(!document.body) return;

    setInterval(function(){
        var a = {};
        a.a = new Date();
        a.b = a.a.getDay();
        a.c = a.a.getMinutes();
        document.body.innerHTML = a.a.getFullYear() + "年" +
            (a.a.getMonth() + 1) + "月" +
            a.a.getDate() + "日(" +
            ((a.b === 0)? "日": (a.b === 1)? "月": (a.b === 2)? "火": (a.b === 3)? "水": (a.b === 4)? "木": (a.b === 5)? "金": "土") + ") " +
            a.a.getHours() +
            ((a.a.getSeconds() % 2 === 0)? ":" : " ") +
            ((a.c < 10)? "0": "") + a.c;
    }, 500);
})();

『三項演算子』に慣れてないと読みづらさこの上ない感じでファンタスティックですね。アンビリバボーだと感じておられる方が多いかもしれませんが、このくらいの『三項演算子』であるばらばちょいちょい見かけるレベルかと思います。

(´-`).。oO(ちなみに上記のデジタル時計プログラムはたぶん全てのウェブサイトで実行できますので...)

(´-`).。oO(適当なウェブサイトを訪問してコンソールを開いて上記のソースコードをペタッと貼り付けてみてください...)

(´-`).。oO(ちょっとウイルスっぽい動きをしますがただのデジタル時計でございますので...)

(´-`).。oO(G-SHOCKが壊れた時にでもお使い下さればと思います...)

さて、ではこのまま『三項演算子』をささっと読むコツを紹介したいと思います。プログラミングを仕事にするとするならば『『三項演算子』がさくっと読めないよぉ...」という状態はあまりよろしくありませんからね。

まずは『三項演算子』の右側のみ(『false』の方)に『三項演算子』が含まれているパターンで、これは結構使用されることが多いです。上記のサンプルだと曜日出力の分岐処理のところが該当しますね。以下の部分です。

(a.b === 0)? "日": (a.b === 1)? "月": (a.b === 2)? "火": (a.b === 3)? "水": (a.b === 4)? "木": (a.b === 5)? "金": "土"

まず『:』の右側で改行してあげましょう。

(a.b === 0)? "日":
(a.b === 1)? "月":
(a.b === 2)? "火":
(a.b === 3)? "水":
(a.b === 4)? "木":
(a.b === 5)? "金":
"土"

続いて1行目に注目します。

(a.b === 0)? "日":

この条件が成立するならば『?』の右側(『:』の左側)が問答無用で実行されます。

もし条件が成立しなかった場合は次の行へ進みます。

(a.b === 1)? "月":

これも先ほどと同じく、条件が成立するならば『?』の右側(『:』の左側)が問答無用で実行されます。

と、こんな感じで全ての行を繰り返して最後まで成立しなかったら最後の行が実行されます。

"土"

これだけです。

つまり『三項演算子』の左側の式に『三項演算子』が含まれず右側の式のみに『三項演算子』が含まれるパターンならば『最初の条件を読む → 成立するなら『?』の右隣 → 成立しないなら次の条件 → 成立するなら『?』の右隣 ...』という感じで読み進めればOKです。

複雑そうにみえて、実は書いてある順番通りに左から処理が行われているのが分かりますでしょうか。左から順番に読めばいいだけなので慣れちゃうと簡単です。恐らく『:』で改行する必要すらなくなるでしょう。

続いて『三項演算子』の左側の式のみ(『true』の方)に『三項演算子』が含まれていたパターンです。以下のようなパターンですね。

var x = {};
// 適当に処理...
// ...
// ...
// ...

(x.a)? (x.b)? (x.c)? (x.d)? (x.e)? (x.f)? (x.g)? 1: 2: 3: 4: 5: 6: 7:8;

この場合はまず『?』の右で改行をしつつ字下げをしてみましょう

var x = {};
// 適当に処理...
// ...
// ...
// ...

(x.a)?
    (x.b)?
        (x.c)?
            (x.d)?
                (x.e)?
                    (x.f)?
                        (x.g)?
                            1: 2: 3: 4: 5: 6: 7: 8;

続いて『:』の右側で改行をしつつ字上げをします。字下げではなく字上げなので間違えないようにしてくださいね。

var x = {};
// 適当に処理...
// ...
// ...
// ...

(x.a)?
    (x.b)?
        (x.c)?
            (x.d)?
                (x.e)?
                    (x.f)?
                        (x.g)?
                            1:
                        2:
                    3:
                4:
            5:
        6:
    7:
8;

はい、これでOKです。そしたら最初の判別式を読みましょう。上記のサンプルだと『x.a』ってやつですね。これが『true』扱いされる値ならば右(右斜め下)へ進みます。

var x = {};
// 適当に処理...
// ...
// ...
// ...

(x.a)?
    (x.b)? // 『x.a』が『true』扱いされるならばここへ進みます。
        (x.c)?
            (x.d)?
                (x.e)?
                    (x.f)?
                        (x.g)?
                            1:
                        2:
                    3:
                4:
            5:
        6:
    7:
8;

最初の判別式(『x.a』)が『false』扱いされるなら下へ進みます。

var x = {};
// 適当に処理...
// ...
// ...
// ...

(x.a)?
    (x.b)?
        (x.c)?
            (x.d)?
                (x.e)?
                    (x.f)?
                        (x.g)?
                            1:
                        2:
                    3:
                4:
            5:
        6:
    7:
8; // 『x.a』が『false』扱いされるならばここへ進みます。

これを繰り返すだけです。判別式が出てくる度にその評価が『true』扱いされるなら右へ、『false』扱いされるならば同じ段の下へ進むだけでOKです

var x = {};
// 適当に処理...
// ...
// ...
// ...

(x.a)? // 判別式の評価が『true』扱いされるならば右へ進みます。『false』扱いされるならば同じ段の下に進みます。
    (x.b)?
        (x.c)?
            (x.d)?
                (x.e)?
                    (x.f)?
                        (x.g)?
                            1:
                        2:
                    3:
                4:
            5:
        6:
    7:
8;

そしてこの方法を使用すれば『三項演算子』の中に『三項演算子』がざっくばらんに存在してる魔界のようなソースコードでも対応することができます。

var x = {};
// 適当に処理...
// ...
// ...
// ...

// 元のソースコードは以下です。
// (x.a)? (x.b)? (x.c)? (x.d)? (x.e)? (x.f)? (x.g)? 1: 2: 3: 4: 5: 6: (x.h)? (x.i)? 7: (x.j)? (x.k)? 8: 9: 10: (x.l)? 11: 12: 13;

// 先ほどの方法で『?』の右で改行と字下げ、『:』の右で改行と字上げを入れてあげればさくっと読めるようになります。
(x.a)? // 判別式の評価が『true』扱いされるならば右へ進みます。『false』扱いされるならば同じ段の下に進みます。
    (x.b)?
        (x.c)?
            (x.d)?
                (x.e)?
                    (x.f)?
                        (x.g)?
                            1:
                        2:
                    3:
                4:
            5:
        6:
    (x.h)?
        (x.i)?
            7:
        (x.j)?
            (x.k)?
                8:
            9:
        10:
    (x.l)?
        11:
    12:
13;

いかがでしょうか。かなり読みやすくなったと思います。

尚、上記の方法は『桜舞式条件演算子両斬波』と呼ばれ魑魅魍魎どもにすら恐れられる一子相伝の秘奥義
著者が独自に行っている読解方法なので「まだダメだぜぇ」って方はgoogle先生に聞いてみると良いかもしれませんね。世界は広いです。ひょっとしたらもっと読みやすい方法があるかもしれません。その辺は適宜対応してしまって下さい。

さて、こんな感じで『三項演算子』はちょっとした分岐処理がささっとかけるので『if文』よりも使い勝手が良さそうな感じがしますがその反面、『三項演算子』で書かれたソースコードは読みづらいと感じる方が多いのも事実です。

しかも『三項演算子』はC言語の頃から存在している構文で歴史がかなり古く、プログラム経験が深い人と浅い人で慣れの部分に大きく差が出てしまう傾向がありますのでご注意です。

実際に「『三項演算子』は使用禁止」としている企業さんも稀に存在しますので「『三項演算子』は好みが別れる構文」ということも合わせて覚えておくようにして下さい。

(´-`).。oO(ちなみに著者は『三項演算子』が大好きです...)

(´-`).。oO(しかし、最後に紹介したサンプルのような『三項演算子』の中で複数の『三項演算子』というパターンは...)

(´-`).。oO(読めるかと聞かれれば読めますが、読みづらいかと聞かれれば読みづらいので...)

(´-`).。oO(著者は皆様に書かないようにすることを勧めます...)

この記事で紹介している『?』と『:』を使った構文の正式な呼び名は『三項演算子』ではなく『条件演算子』だったりします。

『三項演算子』とは『3つの式(オペランド)を使用する演算子』という意味になり、足し算で使用する『+』とか掛け算で使用する『*』とかは左辺と右辺の2つのオペランドで処理を行うので『二項演算子』、符号反転を行う『-』(『-10』や『-Infinity』などで使用する『-』)とかは1つのオペランドに処理を行うので『単項演算子』なんて呼ばれたりしますね。

そんでもって、なんで『条件演算子』が『三項演算子』と呼ばれるようになったかというと3つの式(オペランド)で処理をする演算子が『条件演算子』しか存在しないプログラム言語が多いので『"条件演算子" == "三項演算子"』になっちゃったっていうパターンだったりします。

なので『条件演算子』のことを『三項演算子』と呼ぶ人の方が多いです。

ただし、難しめの参考書などでは『条件演算子』と書いてあることもあるので『条件演算子』という呼び名も覚えておくようにしましょう。

というわけで非常に長くなりましたが以上です。ここまでお付き合い頂き大変光栄でございます。

続いての記事では例外処理についてやっていきましょう。ではこの辺で失礼致します。

This article was written by Sakurama.

Author's beloved small mammal

桜舞 春人 Sakurama Haruto

A Tokyo-based programmer who has been creating various content since the ISDN era, with a bit of concern about his hair. A true long sleeper who generally feels unwell without at least 10 hours of sleep. His dream is to live a life where he can sleep as much as he wants. Loves games, sports, and music. Please share some hair with him.

If you find any errors or copyright issues, please .