見出し画像

JavaScript $.each と for(...in...)の並び順について

仕事用備忘録。

JavaScriptの$.each文とfor(...in...)文の並び順について

少し躓いたため、メモメモ。。


現象

ある案件の選択ボックスの中身がコード順に並ばない。

選択ボックスの中身は連想配列で複数組入っている。

簡単にいうと

名称(コード番号)
   ・
   ・

を表示するボックス内で小さい数字から順に並んでほしいのだが、

名称(1120)
名称(4569)
名称(0110)

のように

「なぜか0始まりのコードだけ後ろに回される」という現象。

0始まりだけ後ろに存在する以外は、

コード順に並んでいる。

ちなみにこのデータはSQLで引っ張ってきており、

SQLではきちんと小さい数字順に並んでいる。


ソースコード

JavaScriptソース

// aボタンが押された時
$('.button_a').on('click', function(){
		
		$('.button_a').removeClass('isActive');
		$('.button_b').removeClass('isActive');

// aとbのリストのオプションを消す
        $('.a_list option').remove();
	    $('.b_list option').remove();

// aとbのリストの最初(配列でいうと[0])に「選択してください。」の文言追加
	    $('.a_list').append($('<option>').text('選択してください。').attr('value', 0));
	    $('.b_list').append($('<option>').text('選択してください。').attr('value', 0));
		$(this).toggleClass('isActive');

//ajaxでデータ取得(オプションは割愛)
		$.ajax({
			url: '<?php echo Router::url(array('controller' => '', 'action' => ''));?>',
			type: "GET",
	        data:{
	            "" : $(this).val()
	        },
			cache: false,
			async: false,
			dataType: 'json',
//成功したら
	        success: function(data){

//「選択してください。」の分、件数を1個マイナス ⇒ 後で件数を使用			
        	 a_count = -1;
        
//each文で繰り返し処理
	             $.each(data, function(id, name){

//disp_nameという変数に名称を代入
				 	disp_name = name;

//idが0より大きいなら(すべて)リスト内に「名称(id)」という文言を格納する
//ついでにid値をvalue属性に付加しておく
				 	if (id > 0) {
				 		disp_name = disp_name + '(' + id + ')';
				 	}
	             	$('.a_list').append($('<option>').text(disp_name).attr('value', id));
				 	a_count++;
	             });
				}

//aのリストの上に隠していたメッセージエリアを可視化する ⇒ ここで件数を使用
				$('#a_message_area').show();
				$('#a_message_area').text(a_count + '件が見つかりました。');
	        },

// データ格納に失敗したらエラーページへ
	        error: function(){
				location.href='<?php echo Router::url(array('controller' => '', 'action' => 'error'));?>';
	        }
		});
	});

コードの内容が分かりづらいかもしれないが、

aのリストを構成するのがこの内容ということである。

isActiveはよくわからないが、多分いるのでおいとく。

bのリストも同じ感じで下にある。

今回はeachの繰り返し処理の並びがおかしいという話なので割愛。


原因

JavaScript each で検索かけたところ、

並び順を保証しないメソッドであるとのこと。

保証していないというより、あまり柔軟な決め事ができない?

既にeachの中で決まっている並びがあるんだと感じた。

数字は1.2.3......9.0の並びとか?かな。

ようわからんけども。


対策1.if文で並びを変えてみる

単純にeach文をif条件分岐で2つ用意して、

idが低い方から並ぶのでは?という予想。

変更後コード

	     success: function(data){		
         a_count = -1;
	     $.each(data, function(id, name){
		   disp_name = name;

//★ここから変更★
			if (id > 0 
                && id < 1000) {
					disp_name = disp_name + '(' + id + ')';
     	           	$('.a_list').append($('<option>').text(disp_name).attr('value', id));
	    	     	a_count++;
            }else if( id >= 1000){
                    disp_name = disp_name + '(' + id + ')';
     	          	$('.a_list').append($('<option>').text(disp_name).attr('value', id));
	    			a_count++;
	        });
		  }
//★ここまで★


				$('#a_message_area').show();
				$('#a_message_area').text(a_count + '件が見つかりました。');
	        },
	        error: function(){
				location.href='<?php echo Router::url(array('controller' => '', 'action' => 'error'));?>';
	        }
		});
	});

結論 ⇒ 無意味。

変わらない。

並び順変わらない。


対策2.for(...in...)文で並びを変えてみる

最終的なコードがこちら

  success: function(data){
  
  //★ここから変更★
			for(var id in data){
				if(id > 0 && id < 1000){
					disp_name = data[id] + '(' + id + ')';
					$('.a_list').append($('<option>').text(disp_name).attr('value', id));
				}
			}
			for(var id in data){
				if(id >= 1000){
					disp_name = data[id] + '(' + id + ')';
					$('.a_list').append($('<option>').text(disp_name).attr('value', id));
				}
			}
			$('#bank_message_area').show();
			$('#bank_message_area').text((Object.keys(data).length - 1 ) + '件が見つかりました。');
	        },
//★ここまで★

結論 ⇒ OK

並び順は希望通り、小さい数字順に変わった。

コード的に何が変わったかというと、

・each ⇒ for
・name ⇒ data[id] (ここだけ最初、表記の仕方が分からなかった)
・a_count++; ⇒ 無し
・a_count ⇒ Object.keys(data).length

くらい。

countは連想配列に使えないため、Object.keys().lengthに変更して

件数を取得した。

ちなみに、こちらでも条件分岐している意味はあるかというと、ある。

for(...in...)でも最初のコードのように

for(var id in data){
				if(id > 0 ){
					disp_name = data[id] + '(' + id + ')';
					$('.a_list').append($('<option>').text(disp_name).attr('value', id));
				}
			}

だけだと、数字は小さい順には並ばない。


まとめ

each文もfor(...in...)文も並び順は一緒。

JavaScriptの仕様なのかな?

JavaScriptはほとんど使わないからわかりません。

調べる気にもなりません。

ただ、for(...in...)文を条件分岐してみると、

並びは変えてくれた。

each文は分岐させても一緒だった。

つまり、総合的に統合した段階で判別している?

並びを決めるコードを実際に実行する段階の違いという結論。

繰り返し処理 ⇒ データ格納 ⇒ その他 ⇒ 画面表示

       ↑forはここ         ↑eachはここ

ひとまず、そうゆうことにしとこう。

この記事が気に入ったらサポートをしてみませんか?