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

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

ただいまの
回答率

89.62%

JavaScriptで、if文の論理演算子OR(||)がうまいこと機能していない

解決済

回答 6

投稿

  • 評価
  • クリップ 2
  • VIEW 2,322

Beginnerrr

score 15

 作ろうとしているもの

生年月日をプルダウンで選択出来るものを作っています。
選択する西暦・月によって、選択出来る日数を変えられる様にしています。
なので、西暦や月の値を変える度に、日数のデータは空になり、選択出来る日数の値が変わります。
具体的には、「うるう年の2月は29日まで選択できるが、それ以外の年の2月は28日までしか選択できない。」です。

 問題点

問題があるコードはたぶん、JavaScriptの1個目の「else if」だと思います。
1、3、5、7、8、10、12月は日数が31日まであるので、31日までプルダウンで表示したいです。
しかし、1月は31日まで選択出来るのですが、それ以外の月は何故か30日までしか表示されません。
「検証」を使って、「month_value == (1||3||5||7||8||10||12)」を実行してみたのですが、
month_valueの値とカッコ内の先頭の数字が一致する場合しかTRUEを返しません。
全く訳が分からない状況です。
何方か教えて頂きたいです。

 コード

const monthCheck = function(){
    var year_value = document.getElementById("year").value;
    var month_value = document.getElementById("month").value;
    year_value = parseInt(year_value);
    month_value = parseInt(month_value);

    var x = document.form_signin.day;
    if (x.hasChildNodes()) {
        while (x.childNodes.length > 0) {
            x.removeChild(x.firstChild)
        }
    }


    if(year_value%4 == 0 && month_value == 2 ){                   //29
        for(var i=1; i<30; i++){
            document.form_signin.day.options[i] = new Option(i+"日", i); 

        }
    }else if(month_value == (1||3||5||7||8||10||12) ){  //31 
        for(var i=1; i<32; i++){
            document.form_signin.day.options[i] = new Option(i+"日", i);
        }
    }else if(month_value == 2 ){                              //28
        for(var i=1; i<29; i++){
            document.form_signin.day.options[i] = new Option(i+"日", i);
        }
    }else{                                                    //30
        for(var i=1; i<31; i++){
            document.form_signin.day.options[i] = new Option(i+"日", i);
        }
    }
}
<form name="form_signin">
                          <select name="year" id="year" class="w100" onchange="monthCheck()" >
                                <option value="1">--西暦--</option>
                                <option value="1980">1980年</option>
                                <option value="1981">1981年</option>
                                <option value="1982">1982年</option>
                                <option value="1983">1983年</option>
                                <option value="1984">1984年</option>
                                <option value="1985">1985年</option>
                                <option value="1986">1986年</option>
                                <option value="1987">1987年</option>
                                <option value="1988">1988年</option>
                                <option value="1989">1989年</option>
                                <option value="1990">1990年</option>
                                <option value="1991">1991年</option>
                                <option value="1992">1992年</option>
                                <option value="1993">1993年</option>
                                <option value="1994">1994年</option>
                                <option value="1995">1995年</option>
                                <option value="1996">1996年</option>
                                <option value="1997">1997年</option>
                                <option value="1998">1998年</option>
                                <option value="1999">1999年</option>
                                <option value="2000">2000年</option>
                                <option value="2001">2001年</option>
                                <option value="2002">2002年</option>
                                <option value="2003">2003年</option>
                                <option value="2004">2004年</option>
                                <option value="2005">2005年</option>
                                <option value="2006">2006年</option>
                                <option value="2007">2007年</option>
                                <option value="2008">2008年</option>
                                <option value="2009">2009年</option>
                                <option value="2010">2010年</option>
                                <option value="2011">2011年</option>
                                <option value="2012">2012年</option>
                                <option value="2013">2013年</option>
                                <option value="2014">2014年</option>
                                <option value="2015">2015年</option>
                        </select>
                        <select name="month" id="month" class="w80" onchange='monthCheck()' >
                            <option value="0">-月-</option>
                            <option value="1">1月</option>
                            <option value="2">2月</option>
                            <option value="3">3月</option>
                            <option value="4">4月</option>
                            <option value="5">5月</option>
                            <option value="6">6月</option>
                            <option value="7">7月</option>
                            <option value="8">8月</option>
                            <option value="9">9月</option>
                            <option value="10">10月</option>
                            <option value="11">11月</option>
                            <option value="12">12月</option>
                        </select>

                        <select name="day" id="day" class="w80" >
                            <option value="0">-日-</option>
                        </select>
</form>


よろしくお願いします!!!

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 6

+4

javascriptのor演算子||は真(非ゼロ)が見つかった時点で評価を打ち切ります。
したがって、1||3||5||7||8||10||12と書くと、最初の1が真なので1と書いたのと同じことになってしまいます。

つまり当該行は
}else if(month_value == 1 ){
になってしまいます。

といって、if文を並べるのもイヤというなら、配列[1,3,5,7,8,10,12]を作って、その中にmonth_valueが含まれるかどうか調べればいいです。

新し目のJSの配列にはArray.prototype.includes()メソッドがあるので簡単です。もし同メソッドが使えなければ、[1,3,5,7,8,10,12].indexOf(month_value) >= 0で調べることができます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+3

しつこいようですが、変な条件で閏年や小の月を探すのは無駄が多いのでやめたほうがいいでしょう

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/08/07 16:00

    自分はすぐ年月日をまとめて入力できるCalendarライブラリーとか導入してValidationはサーバーサイドで片付けちゃいますけど
    こういう独自実装が必要な場合変な条件にならないよう、どうやるのがスマートなんですかね

    キャンセル

  • 2018/08/07 16:43

    一番スマートなのはカレンダーデータを別途もつこと
    そうでない場合は、前回の質問で回答したように
    https://teratail.com/questions/139964
    年と月を指定してその月の月末日までを表示するだけなので
    if(月が大の月なら)的な条件分岐自体が不要

    キャンセル

  • 2018/08/07 16:54

    前日譚?があったんですね確かに年月から日にちをぶん回すだけで事足りますね。ありがとうございました。

    キャンセル

  • 2018/08/07 17:37

    ご指摘有難うございます!
    あのコードを理解できる様に頑張ります!

    キャンセル

checkベストアンサー

+2

}else if(month_value == (1||3||5||7||8||10||12) ){  //31


こういう横着は、どの言語を使ってもできないように思います。
以下のようにすべきです。

}else if(
  month_value == 1 ||
  month_value == 3 ||
  month_value == 5 ||
  month_value == 7 ||
  month_value == 8 ||
  month_value == 10||
  month_value == 12
  ){  //31

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/08/07 14:48

    捕捉で、どうしても1行で書きたければ下記を参照してみてはどうでしょう。
    https://teratail.com/questions/65669

    キャンセル

  • 2018/08/07 14:49

    知りませんでした、、、
    有難うございます!!!
    頭のモヤが晴れました。

    キャンセル

  • 2018/08/07 15:02 編集

    蛇足ですけど(1||3||5||7||8||10||12)だと
    1はtrueか?じゃなければ3、左の結果はtrueか?でなければ5、・・・
    と言う感じになります。
    jsの場合falseとする値は0や空文字化などでありそれ以外はすべてtrueになります。
    詳しくはJavaScriptの「&&」「||」の解説(https://qiita.com/Imamotty/items/bc659569239379dded55)を見ればよくわかります。

    キャンセル

+2

var m31 = [1,3,5,7,8,10,12];
if(m31.includes(month_value)){ // 31


↑のようにする手も。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+2

year_value%4 == 0 && month_value == 2

そもそもこれ、うるう年の判定として落第です。
もうこういうのは専門家に任せましょう。

というわけでMoment.jsを覚えてみては?
Browser - Moment.js Docを見る限り、
CDNが公開されており、1行のスクリプトタグを貼り付けるだけで利用可能となります。

そしてMoment.jsにはDays in Monthというまさにあなたの為に専門家が作ったような機能が用意されています。

var year = 2016;
var month = 2;
var days = moment([year, month - 1]).daysInMonth(); // month: -1が必要なのに注意すること

ほら、たった1行で済みました。
JSで凝った日付管理がしたければMoment.jsを頼るくらいで良いかと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/08/07 16:32

    有難うございます!!!
    こんな便利なものがあるんですね!!!

    キャンセル

+1

質問の内容から脱線しますが、「配列等に規定値を突っ込んでおいて評価する」ってやると、コードがきれいに書けます。
JavaScript での書き方がちょっとわからなかったので、コードは適当です。

test_arr =[1,2,3,0,100]; 
month_days ={1:31,2:28,3:30};//めんどいので3月までw
year = 2000;
test_arr.forEach(function(month) {
    if(month === 0||month > 12){
        console.log('error');//エラーの対応
    }
    if(month===2){
        if(year%4===0&&year%100!==0){//うるう年の判定
        month_days[2]=29;
        }
    }
    console.log(month+'月の最終日:'+month_days[month]);//キモ
});

//
1月の最終日:31
2月の最終日:28
3月の最終日:30
error
0月の最終日:undefined
error
100月の最終日:undefined

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 89.62%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる