ワイヤード・パンチ

jQueryでeachのループから勝手に抜けてしまうときの対処法。

上の写真のように、チェックボックスのあるフォームを作成しています。

実行ボタンが押されたときにjQueryによって、上から順にチェックボックスの状態を確認し、状態に応じた処理を行おうとしていました。

しかし、すべてのチェックボックスの状態を確認してほしかったのに、1つ目のチェックボックスを確認しただけで処理が勝手に終わってしまいました

広告

今回のコード

言語はJavascriptで、プラグインは定番のjQueryを使用しています。

なお、jsそのままだと記述がめんどくさいので、jsを楽に書けるcoffeescriptも使用しています

checked = true
$('input[type="checkbox"]').each (index) ->
	if $(this).prop("checked") == false
		checked = false

上記のコードではループ内にて、画面上に存在するチェックボックスを一つずつ見ていきます。

チェックボックスの状態を確認して、チェックが入ってないボックスが1つでもあれば、フラグを立てるという処理になっています。

しかし実際にこのコードを実行してみると、冒頭でも書いたとおり、1つ目のチェックボックスの処理が済んだ直後に、ループを抜けてしまいました

つまり、以降のチェックボックスは無視されてしまいました。

eachのループを途中で抜ける処理といえばreturn falseなのですが、return falseは上記のコードにありません

それなのに、なぜループを途中離脱…?

coffeescriptとjs、両方の仕様のせいだった。

先程のcoffeeのコードを、jsに変換したものが以下になります。

var checked;

checked = true;

$('input[type="checkbox"]').each(function(index) {
  if ($(this).prop("checked") === false) {
	return checked = false;
  }
});

coffeeからjsに変換したコードは、処理の最後にreturnが強制的に付く仕様となっています。

それに加えてjsの仕様上、boolean型変数にfalseを代入する処理がreturnで行われた場合も、ループから抜けてしまいます

つまり、return falseと書いたつもりでなくても、勝手にreturn falseに置き換えられてしまったということです。

というわけで、今回の対策は以下のコードになります。

checked = true
$('input[type="checkbox"]').each (index) ->
	if $(this).prop("checked") == false
		checked = false
		return

最後に自動的にreturnを付けられてしまうため、自らreturnを明示的に行っておくことで、return falseになってしまうのを防いでいます。

余談。

記述を楽にするために入れたはずのcoffeeなのに、余計な仕様のために、逆に足を引っ張られてしまいました。

それ以外にも、coffeeではfor文が使えず、whileで代用しないといけないという変な仕様もありますし、改善を願いたいですね…。

なお、現在はcoffeescript2というものが登場しているようです。

試してみたいのですが、普段coffeeからjsへの変換はpreprosで行っています。

でも、残念ながらpreprosはcoffeescript2に未対応

preprosは唯一、黒い画面を見ずにGUIで変換が行えるツールだから、頑張ってほしい…。