(function($){})(jQuery)と$(function(){})と$(document).ready(function(){})について

先日のエントリー「jQuery 〜 なんだか動作が違う」。
どこが間違っているのかに直ぐに気づかずに悩んだ。大分恥ずかしいけど、悩んだのでメモ。

問題は次の3つの書き方のいずれにも同じ動作を期待したのだが、2番目の書き方だけ期待した動作をしないこと。

1つ目。

<!DOCTYPE html>
<html>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<head></head>
<script type="text/javascript" src="jquery-1.4.4.js"></script>
<script type="text/javascript">
$(document).ready(function(){
 var focusFunc = function(){
  alert("focused");
 };
 $('#test input[type="text"]').bind("focus", focusFunc);
});
</script>
<body>
<div id="test">
<input type="text"/><br>
</div>
</body>
</html>

2つ目。

<!DOCTYPE html>
<html>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<head></head>
<script type="text/javascript" src="jquery-1.4.4.js"></script>
<script type="text/javascript">
(function($){
 var focusFunc = function(){
  alert("focused");
 };
 $('#test input[type="text"]').bind("focus", focusFunc);
})(jQuery);
</script>
<body>
<div id="test">
<input type="text"/><br>
</div>
</body>
</html>

3つ目。

<!DOCTYPE html>
<html>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<head></head>
<script type="text/javascript" src="jquery-1.4.4.js"></script>
<script type="text/javascript">
$(function(){
 var focusFunc = function(){
  alert("focused");
 };
 $('#test input[type="text"]').bind("focus", focusFunc);
});
</script>
<body>
<div id="test">
<input type="text"/><br>
</div>
</body>
</html>

1つずつ順番に見ていこう。
まず、1つ目だが、これはjQueryのready関数を使用してDOMがロードされて操作・解析が可能になったタイミングで関数を実行している。
3つ目も同じだ。

問題は、2つ目も同じだと思い込んでしまっていたこと。全く違う。
2つ目は、即時関数なので、関数が定義された瞬間に実行される。つまり、DOMがロードされる前に実行されるのだ。

だから、inputオブジェクトがロードされる前に、$('#test input[type="text"]').bind("focus", focusFunc);を実行してもフォーカスイベントにfocusFuncがbindされるはずがない。

2つ目を書き直すなら、次のようになると思う。

<!DOCTYPE html>
<html>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<head></head>
<script type="text/javascript" src="jquery-1.4.4.js"></script>
<script type="text/javascript">
(function($){
 $(document).ready(function(){
  var focusFunc = function(){
   alert("focused");
  };
  $('#test input[type="text"]').bind("focus", focusFunc);
 });
})(jQuery);
</script>
<body>
<div id="test">
<input type="text"/><br>
</div>
</body>
</html>

基本的なことなんだけど、思い込みや勘違いってあるな。勉強不足という側面もあるが、近くにプロのJavaScript屋がいない場合はどうやって自分を正しい方向に導けば良いのだろうか(読書以外で)。
結局、読書や実践を積み重ねながら1つずつ気づいていくしかないのかな。