Edited at

JavaScriptの条件演算子(三項演算子)読解入門


ソースを見ると現れる不思議な記号たち

他の方が書いたソースを見て勉強させていただくことがよくあります。

そんな時、私のリテラシーが低く

『なんだこれ?なんの言語ですか。。』

となってしまう場合がよくあります。

その最たる例が条件演算子(三項演算子)です。

このテーマで検索をすると、

下記のように「可読性が低いから使わない方がいい!」など、

さまざまな議論があるようです。

条件演算子(三項演算子)を可読性低いとか言わせない

三項演算子?:は悪である。

ただ、私の直近の課題はこの演算子の使用の是非ではなく、

『読んで理解できるようになること!!』

ということで、メモとして残すことにしました。

(注 : JavaScriptのお話であり、他の言語の場合はわかりません。。)


基本形

//変数に代入

let 変数 = 条件式 ? trueの時の値 : falseの時の値 ;

//関数
const f = 条件式 => 条件式 ? trueの時の値 : falseの時の値

上記はそれぞれ下記のif文と同じ。

//変数に代入

let 変数
if (条件式) {
変数 = trueの時の値
} else {
変数 = falseの時の値
}

//関数
const f = 条件式 =>
if (条件式) {
return trueの時の値
} else {
return falseの時の値
}

ここまではOKです。

でもこの三項演算子、入れ子構造になったりするらしいのです。

そこまできたらもうわけわかりません。

ただ、この基本形を見て下記のことがわかりました。


  1. 『 ? のすぐ左は必ず条件式(ifの始まり)』

  2. 『 : はelse』

  3. 『?と:は1対1対応。(?があればそれに対応する:があるはず!)』

この三つの基本法則をもとに読解してみます。


例題1

いま勉強しているソースコードの一部を例に考えてみます。

Slice Revealer - codrops)←ここのやつです。

変数 = !this.isCovered ? this.options.orientation === 'vertical' ? 'translateY(100%)' : 'translateX(100%)' : 'none';

初見で全く意味がわかりませんでした。

なんか「?」と「:」が二つずつあるし。。

でも、さっきの発見をもとに頑張って読解してみます。

下記のような思考回路になりました。


Step1

えっと、?の左は条件式だから。。

まず最初の

!this.isCovered



if(!this.isCovered)

と同じだな。


Step2

お、また『?』が出てきた。?の左は条件式だから、

this.options.orientation === 'vertical'



if(this.options.orientation === 'vertical')

と同じだ!

二個目の『?』が出てきたってことは、これ入れ子の構造確定だな!


Step3

『:』はelseに置き換えればいい。

『?と:は1対1の対応』だけど、最初の『?』に対応する『:』ってなんだろう?

'translateY(100%)'の右の:は

if(this.options.orientation === 'vertical')

にかかるはず。

ってことは最後にでてくる'none'の左の『:』だな。

全体像はこんな感じか!

if(!this.isCovered) {

if(this.options.orientation === 'vertical') {
変数 = 'translateY(100%)';
} else {
変数 = 'translateX(100%)';
}
} else {
変数 = 'none';
}

ここまできたらさすがにわかります。

無事読解できました。


例題2

translateX: this.options.orientation === 'vertical' ? '0%' : 

!this.isCovered ?
this.options.slicesOrigin.show === 'right' ? '100%' : '-100%' :
this.options.slicesOrigin.hide === 'right' ? ['100%','0%'] : ['-100%','0%'],

いよいよわからん。

わかりやすくインデントつけていただいてますが、

優しさ虚しく、私の未熟さゆえにわかりません。

よし、根気よく読解しよう。


Step1

?の左は条件式だから、

最初の

this.options.orientation === 'vertical'



if(this.options.orientation === 'vertical')

と同じ。


Step2

「:」がでてきたな。これはelseだ。つまり1行目まではこういうことか。

if(this.options.orientation === 'vertical') {

translateX: '0%',
} else {
...
}


Step3

また『?』か。二つ目の時点でif入れ子確定だ。

!this.isCovered



if(!this.isCovered)

と同じ。

ちょっと待て。『?』と『:』は1:1対応のはず。この『?』に対応する『:』はなんだろう?

候補は3行目以下にある合計三つ。

でも3行目の最初の『:』は

if(this.options.slicesOrigin.show === 'right')にかかるから違う。

同じように4行目の『:』も違う。

ということは3行目最後の『:』だ!

そうなると全体像は以下の通り!

if(this.options.orientation === 'vertical') {

translateX: '0%',
} else {
if(!this.isCovered) {
if(this.options.slicesOrigin.show === 'right') {
translateX: '100%',
} else {
translateX: '-100%',
}
} else {
if(this.options.slicesOrigin.hide === 'right') {
translateX: ['100%','0%'],
} else {
translateX: ['-100%','0%'],
}
}
}

こういうコードだったのか。


まとめ

プログラミング『言語』というだけあって、やはり英語の勉強に似てるなと思いました。

今回の例を英語に言い換えると、

『関係代名詞that節の後ろは主語+動詞!』と必死に覚えているようなものだなと。

でも、英語の熟練者はいちいちそんなこと考えず自動的に脳内で読み解くと思うんですね。

三項演算子も、何回も書いてきた方にとっては脳内で自動化されて何も意識せず読み解いてしまうと思うのですが、私にはまだ『頭の中でif文に変換する作業』が発生している状態でして。。。

少しでも頭の中をJS脳に近づけたく、この記事を書きました。

「ここがそもそも違います」

「その認識だと、このパターンに対処できないよ」

といったことがございましたら、ご教示いただけますと幸いです。