なぜ無名関数を定義してjQueryを引数として渡すのですか?


96

backbone.jsスクリーンキャストからの優れたpeepcodeデモコードを調べています。その中で、バックボーンコードはすべてjQueryオブジェクトに渡される無名関数で囲まれています。

(function($) {
  // Backbone code in here
})(jQuery);

私自身のバックボーンコードでは、すべてのコードをjQuery DOMの「準備完了」イベントにラップしました。

$(function(){
  // Backbone code in here
});

最初のアプローチのポイント/利点は何ですか?このようにすると、無名関数が作成され、関数の引数としてjQueryオブジェクトが渡されてすぐに実行され、$がjQueryオブジェクトであることを効果的に保証します。これが唯一のポイントですか-jQueryが '$'にバインドされていることを保証するためですか、それとも他の理由がありますか?


4
代わりに最初にSOを参照する必要がありました。
アレクサンダー

他のライブラリとの相互運用性-ページの作成者がを使用する必要がある場合$.noConflict()、最初の例は引き続き機能します。
DCoder 2012

重複の可能性:jQueryと$の質問
Alexander

重複する可能性のあるjQuery document.readyと自己呼び出しの匿名関数の違いを参照してください
Bergi

@Alexanderしかし、他の人はまずSOでこの質問を見つけます。:-)
caiosm1005 2018年

回答:


179

ここまでに示した2つのコードブロックは、実行するタイミングと理由が劇的に異なります。それらは互いに排他的ではありません。それらは同じ目的を果たしません。

JavaScriptモジュール


(function($) {
  // Backbone code in here
})(jQuery);

これは、「JavaScriptモジュール」パターンであり、即座に呼び出す関数で実装されます。

このコードの目的は、コードに「モジュール性」、プライバシー、およびカプセル化を提供することです。

これの実装は、呼び出し(jQuery)括弧によってすぐに呼び出される関数です。括弧にjQueryを渡す目的は、グローバル変数にローカルスコープを提供することです。これは、ルックアップのオーバーヘッドの量を減らすのに役立ちます$変数を検索する圧縮/最適化を改善できます。

すぐに呼び出される関数がすぐに実行されます。関数の定義が完了するとすぐに、関数が実行されます。

jQueryの「DOMReady」関数

これはjQueryの「DOMReady」関数のエイリアスです:http ://api.jquery.com/ready/


$(function(){
  // Backbone code in here
});

jQueryの「DOMReady」関数は、JavaScriptコードでDOMを操作する準備ができると実行されます。

バックボーンコードでのモジュールとDOMReady

jQueryのDOMReady関数内でバックボーンコードを定義するのは不適切な形式であり、アプリケーションのパフォーマンスに悪影響を与える可能性があります。この関数は、DOMが読み込まれ、操作できるようになるまで呼び出されません。つまり、オブジェクトを定義する前に、ブラウザがDOMを少なくとも1回解析するまで待機します。

DOMReady関数の外部でBackboneオブジェクトを定義することをお勧めします。他の多くの人の間で、コードにカプセル化とプライバシーを提供できるように、JavaScriptモジュールパターンの内部でこれを行うことを好みます。「外部モジュール」パターン(上記の最初のリンクを参照)を使用して、モジュールの外部で必要なビットへのアクセスを提供する傾向があります。

DOMReady関数の外部でオブジェクトを定義し、それらを参照する何らかの方法を提供することにより、ブラウザーがJavaScriptの処理をすぐに開始できるようになり、ユーザーエクスペリエンスがスピードアップする可能性があります。また、物事を移動するときにDOMREady関数を作成することを心配することなく物事を移動できるので、コードがより柔軟になります。

バックボーンオブジェクトを他の場所で定義した場合でも、DOMReady関数を使用する可能性があります。その理由は、多くのバックボーンアプリが何らかの方法でDOMを操作する必要があるためです。これを行うには、DOMの準備ができるまで待機する必要があるため、DOMReady関数を使用して、アプリケーションが定義された後でアプリケーションを起動する必要があります。

この例はウェブ上でたくさん見つかりますが、モジュールとDOMReady関数の両方を使用した非常に基本的な実装を次に示します。



// Define "MyApp" as a revealing module

MyApp = (function(Backbone, $){

  var View = Backbone.View.extend({
    // do stuff here  
  });

  return {
    init: function(){
      var view = new View();
      $("#some-div").html(view.render().el);
    }
  };

})(Backbone, jQuery);



// Run "MyApp" in DOMReady

$(function(){
  MyApp.init();
});

1
この詳細な回答に感謝します。私は、DOM Ready関数がDOM readyイベントが発生したときにのみ呼び出すことを知っていましたが、それが問題になるとはまったく思っていませんでした。モジュール内でバックボーンビットを定義するためにコードを分割し、dom readyでそれらとやり取りすることは、確かに最良のアプローチのように見えます
Matt Roberts

2
興味深いことに、バックボーンsrcを含む「todo」サンプルアプリは、domのすべての準備を整えます。
マットロバーツ

2
JavaScriptモジュールパターンはとも呼ばれることを忘れないでくださいIIFE
ジェス

1
匿名関数は基本的にDOMの準備が整うと同時に実行されるため、どのようにしてそれらをより効率的にするのですか?
bhavya_w 2014

14

副次的な注意として、無名関数への引数として$を送信すると、その関数に対して$がローカルになります。これは、$関数がたくさん呼び出された場合、パフォーマンスに小さな影響があります。これは、JavaScriptが最初にローカルスコープで変数を検索してから、ウィンドウスコープ($が通常存在する場所)までずっと下に移動するためです。


9

これは、たとえ使用されたとしても、そのクロージャー内で常に使用できることを保証します。$$.noConflict()

このクロージャーなしjQuery$は、ずっと使用する代わりに使用することになっています。



2

両方を使う。

ライブラリの競合を防ぎ、$で期待するとおりにjQueryが利用可能であることを確認するためにjQueryを渡す自己呼び出し関数。

そして、DOMが読み込まれた後にのみJavaScriptを実行するために必要な.ready()ショートカットメソッド:

(function($) {
    $(function(){
          //add code here that needs to wait for page to be loaded
    });

    //and rest of code here
})(jQuery);

私がSOの他の場所で見つけた短いバージョン(未定義も保護します)jQuery(function ($, undefined) { /* Code */ });
Jared Gotte 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.