質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

2回答

3788閲覧

条件 (三項) 演算子 (?:) (JavaScript)の2重にある?の解釈について

R.lawliet

総合スコア41

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2015/05/26 05:14

現在日付のプルダウンメニューを作るべく、
サイトに乗っている中身を解釈しようと奮闘しています。

?表記のままだとちょっと僕にはスムーズに頭に入らないので、
if elseの形に直したりしているのですが、
この二重に埋め込まれた場合の解体方法が分かりません。

自分なりの解釈で解体してみたら挙動がおかしくなったので、
どこか違う解釈をしているみたいです。

ご指導よろしくお願いします。

↓以下部分的に抜粋したもの

lang

1option.disabled = 2( Year==NowYear && Month==NowMonth ) ? 3( ( d<NowDate ) ? 'disabled' : false ) : false; 4

個人的解釈

lang

1if(Year == NowYear &&Month == NowMonth){ 2 if(d < NowDate){ 3 option.disabled = 'disabled'; 4 }else{ 5 false; 6}else{ 7 false; 8}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

あら、すぐ出来そうだったので、鼻歌歌いつつやってたら先に回答が付いていましたね。(^^;)
ShunsukeIzuiさんのお答えが全てで、これでもう十分かとは思いますが、

最初に提示されたコードを拝見した際に感じた不安感と、ShunsukeIzuiさんの提示されたコードを見たときの反応から不安感を感じたので、蛇足として付けたしておきます。

不要だと思われたら読み飛ばしてください。

まず、考え方として、
そもそも、**何をしたいのか?**をしっかり把握することです。

今回、?を用いた三項演算子のとりわけ、それがネストされている物をif文で表したいのですが
それは、事象にすぎなくて、本当にやりたいのは、どんな方法かはさておき、
option.disabledの値を設定したい
これが、キモです。ここが分っていないと、スタート地点につけません。

option.disabledが設定したいということを導きだすのは、
元のコードが

lang

1option.disabled = 2( Year==NowYear && Month==NowMonth ) ? 3( ( d<NowDate ) ? 'disabled' : false ) : false;

こうなっているなら、試しに1文で書いてみましょう。
すると、こうなるはずです。

lang

1option.disabled = ( Year==NowYear && Month==NowMonth ) ? ( ( d<NowDate ) ? 'disabled' : false ) : false;

そうしたら、これは、難しいことを、ぜーーんぶはしょると、

lang

1option.disabled = 何かとにかく三項演算子のネストが評価された後の値;

であると言えます。

したがって、if文で書く時も、何をどうしようが、とにかく、
option.disabledに値を設定しないことには始らない
ということが分るはずです。

これを踏まえてなかったため、今回のミスが起こっていると考えられます。
ですので、まず、この考え方をしっかり持ってください。

プログラマは顧客の業務を電子化し、これにより、作業効率を改善し、人件費等の軽減を行うことが、プログラミングとして依頼されていることであるといえ、
したがって、組み上げるべきコードは、顧客の業務をよく理解し、
そもそも、何がしたいのか?
これを見失っていると、正しいコードが書けません。物事の本質を見抜く目を養いましょう。

話がそれましたね、では、今やりたいのは、option.disabledに値を設定することであると分りました。

その上で、ネストしている三項演算子があるならば、そのネストを解いて順番にif文へ作り変えて行けばいいわけです。

ネストしているときは、一番内側(ネストの最深部)から取りかかるといいでしょう。

一番内側は
option.disabled =
( Year==NowYear && Month==NowMonth ) ?
**( ( d<NowDate ) ? 'disabled' : false ) **: false;
この太字の部分ですね?式の括弧は式を最終的に論理値として評価してこれを利用するためにあるので、
実質的には、一番内側は
( d<NowDate ) ? 'disabled' : false
これですね。

三項演算子は、?の左部分を評価し(つまりif文で置き換えるときの条件式になる)、trueなら:の左の2番目の項の値を返し、falseなら:の右の3番目の項の値を返します(評価値として返す)。

したがって、まず、この部分をif文にするならこうなります。

( d<NowDate ) ? 'disabled' : false 元がこうなので、三項演算子の?の左の評価式をif文の条件式にもってきて

if ( d<NowDate ) { // 三項演算子の?の左の評価式を条件式へもってくる。
//式の評価がtrueならば、三項演算子式の:の左の2番目の項が評価値として利用されるので
//まずは、2項目を置いておきましょう。
'disabled'
} else { //式が成立しなかった場合も記述しなければならないので当然elseが必要です
//式の評価がflseならば、三項演算子式の:の右の3番目の項が評価値として利用されるので
//まずは、3項目を置いておきましょう。
false
}

ここで安心してしまってはいけません。
なぜなら、やりたいことはoption.disabledに値を設定することだからです。現状ではif文へ変換する過程でそれが失われてしまっていますね?
なので、それを補ってあげましょう。すると、こうなるはずです。

lang

1if ( d<NowDate ) { 2 option.disabled = 'disabled'; 3} else { 4 option.disabled = false; 5} 6

これで、一番内側の三項演算子式をif文へと変換できました。
そして、このif文のもとになった三項演算子式そのものが、さらに上位に三項演算子式の一つの項になっているわけですから

option.disabled =
( Year==NowYear && Month==NowMonth ) ?
**if文に変換が終わっている部分 **: false;
現状はこうなってますので、いったん今作ったものは脇へどけておいて、この外側の三項演算子式をif文へ変換しましょう。

option.disabled = ( Year==NowYear && Month==NowMonth ) ? **if文に変換が終わっている部分 **: false;
元がこうなので、三項演算子の?の左の評価式をif文の条件式にもってきて

if ( Year==NowYear && Month==NowMonth ) { // 三項演算子の?の左の評価式を条件式へもってくる。
//式の評価がtrueならば、三項演算子式の:の左の2番目の項が評価値として利用されるので
//まずは、2項目を置いておきましょう。
**if文に変換が終わっている部分 **
} else { //式が成立しなかった場合も記述しなければならないので当然elseが必要です
//式の評価がflseならば、三項演算子式の:の右の3番目の項が評価値として利用されるので
//まずは、3項目を置いておきましょう。
false
}

こうなりますね?ここでも、何をやりたいのかを見失わずに、やりたいことを保管してやりましょう。
するとこうなります。

lang

1if ( Year==NowYear && Month==NowMonth ) { 2 option.disabled = **if文に変換が終わっている部分 **; 3} else { 4 option.disabled = false; 5}

ここまで来たら、もう一息です。いったんどけておいた、先に**if文に変換が終わっている部分 **を取り込んで置き換えて統合してしまいましょう。

lang

1if ( Year==NowYear && Month==NowMonth ) { 2 option.disabled = if ( d<NowDate ) { 3 option.disabled = 'disabled'; 4 } else { 5 option.disabled = false; 6 } 7 ; 8} else { 9 option.disabled = false; 10}

お気づきになりましたか?ShunsukeIzuiさんが、 R.lawlietさんは、分っているであろうから、あえて指摘してなかったことがあることに。

それは、内側のif文のelseを閉じる}が抜けていることです。

if文をネストいていくと、こういったケアレスミスによるバグの作りこみが発生しやすくなり、
後々デバッグするのに苦労します。しかし、今まで提示してきたように、きちんとした考え方を理解してれば、このようなミスは防げます。

さて、ここまでくると、最後はコードの整理といいますか、整合性を取ることです。

この部分、
option.disabled = if ( d<NowDate ) {
option.disabled = 'disabled';
} else {
option.disabled = false;
}
;

option.disabledに値を設定するための方法が、もう一度ifを実行することになっていますが、
ifの中でoption.disabledを設定していますので、ifの外側でのoption.disabledへの代入は必要ないことが分ります。
よって整理するとこうなります。

lang

1if ( Year==NowYear && Month==NowMonth ) { 2 if ( d<NowDate ) { 3 option.disabled = 'disabled'; 4 } else { 5 option.disabled = false; 6 } 7} else { 8 option.disabled = false; 9}

はい、 ShunsukeIzuiさんが提示されたコードになりましたね?

あとは、インデントを整えて、
まぁ、このサンプル単体で動作可能にするなら、最終的にはこうなります。

lang

1<HTML> 2<HEAD> 3 <meta http-equiv="Content-Type" content="text/html; charset=euc-jp"> 4</HEAD> 5<BODY> 6 7<script type="text/javascript"> 8<!-- 9var option = new Object; 10 11var Year = 2015; 12var Month = 5; 13var Day = 10; 14var d = new Date( Year, Month-1, Day); 15 16var NowDate = new Date(); 17var NowYear = NowDate.getFullYear(); 18var NowMonth = NowDate.getMonth() + 1; 19 20if(Year == NowYear && Month == NowMonth){ 21 if(d < NowDate) { 22 option.disabled = 'disabled'; 23 } else { 24 option.disabled = false; 25 } 26} else { 27 option.disabled = false; 28} 29// --> 30</script> 31</BODY> 32</HTML>

長々、蛇足にお付き合いいただきありがとうございました。
どんな時でも、そもそも何をしたいのか? そのために手段として、今何をやっているのか
ここがブレないようにしてください。そして、一つ一つ積み上げていくことが、最終的なゴールへとたどり着くことになります。

投稿2015/05/26 07:31

nekora

総合スコア501

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

R.lawliet

2015/05/26 12:40

心の底を見透かされたかの様で感服致します・・・ コードに性格が出るっていうのは本当なのですね笑 はい、僕は良くその言葉を言われます。 目的がズレている、と。 インデントを単に忘れていたのだろうと自分でも解釈していましたが、 考え方、理解の仕方の段階で発生してしまったミスだったのですね。 教科書以上の分かりやすい順を追った解説をありがとう御座います。 躓く度に読み返して完全に自分のモノにしたいと思います!
guest

0

ベストアンサー

解釈の仕方自体は間違ってはいないと思います。
ただ少しコードが間違ってます。
正しくは次のようにします。

lang

1if(Year == NowYear &&Month == NowMonth){ 2 if(d < NowDate){ 3 option.disabled = 'disabled'; 4 }else{ 5 option.disabled = false; 6 } 7}else{ 8 option.disabled = false; 9}

投稿2015/05/26 05:18

orange0190

総合スコア1698

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

R.lawliet

2015/05/26 05:22

上手く行きました!! ありがとうございます♪ trueやfalseの時も = で繋げなきゃなんですね。 勉強になりました。
orange0190

2015/05/26 05:25

少し解説すると、最初のコードを見るとopttion.disabledを設定していることがわかります。したがって、if elseで書いた場合にはどの様な場合においてもoption.disabledを設定しなければなりません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問