107 Stimmen

Warum eine anonyme Funktion definieren und sie jQuery als Argument übergeben?

Ich schaue mir den ausgezeichneten Peepcode-Demo-Code aus den Backbone.js-Screencasts an. Darin ist der Backbone-Code alle in einer anonymen Funktion eingeschlossen, die dem jQuery-Objekt übergeben wird:

(function($) {
  // Backbone-Code hier
})(jQuery);

In meinem eigenen Backbone-Code habe ich einfach meinen gesamten Code in das jQuery-DOM-'ready'-Ereignis eingewickelt:

$(function(){
  // Backbone-Code hier
});

Was ist der Sinn/Vorteil des ersten Ansatzes? Auf diese Weise wird eine anonyme Funktion erstellt, die sofort mit dem jQuery-Objekt als Funktionsargument ausgeführt wird und somit sicherstellt, dass $ das jQuery-Objekt ist. Ist das der einzige Grund - um sicherzustellen, dass jQuery an '$' gebunden ist oder gibt es andere Gründe, dies zu tun?

188voto

Derick Bailey Punkte 70483

Die beiden Codeblöcke, die Sie gezeigt haben, unterscheiden sich dramatisch in ihrem Zeitpunkt und Zweck ihrer Ausführung. Sie sind nicht ausschließlich voneinander abhängig. Sie dienen nicht dem gleichen Zweck.

JavaScript-Module

(function($) {
  // Backbone-Code hier
})(jQuery);

Dies ist ein "JavaScript-Modul"-Muster, implementiert mit einer sofort aufrufenden Funktion.

Der Zweck dieses Codes ist es, "Modularität", Privatsphäre und Kapselung für Ihren Code bereitzustellen.

Die Implementierung davon ist eine Funktion, die sofort durch den Aufruf von (jQuery) in den Klammern aufgerufen wird. Der Zweck, jQuery in die Klammern zu übergeben, besteht darin, eine lokale Begrenzung für die globale Variable bereitzustellen. Dadurch wird der Overhead beim Suchen der Variablen $ reduziert und in einigen Fällen eine bessere Komprimierung/Optimierung für Minifizierer ermöglicht.

Sofort aufrufende Funktionen werden unmittelbar, nun ja, sofort ausgeführt. Sobald die Funktionsdefinition abgeschlossen ist, wird die Funktion ausgeführt.

jQuery's "DOMReady" Funktion

Dies ist ein Alias für die "DOMReady" Funktion von jQuery: http://api.jquery.com/ready/

$(function(){
  // Backbone-Code hier
});

Die "DOMReady" Funktion von jQuery wird ausgeführt, wenn der DOM bereit ist, von Ihrem JavaScript-Code manipuliert zu werden.

Module vs DOMReady im Backbone-Code

Es ist schlechter Stil, Ihren Backbone-Code innerhalb der jQuery "DOMReady" Funktion zu definieren und potenziell schädlich für die Leistung Ihrer Anwendung. Diese Funktion wird erst aufgerufen, wenn der DOM geladen und bereit ist, manipuliert zu werden. Das bedeutet, dass Sie darauf warten, bis der Browser den DOM mindestens einmal analysiert hat, bevor Sie Ihre Objekte definieren.

Es ist eine bessere Idee, Ihre Backbone-Objekte außerhalb einer DOMReady-Funktion zu definieren. Ich und viele andere ziehen es vor, dies innerhalb eines JavaScript-Modulmusters zu tun, um eine Kapselung und Privatsphäre für meinen Code bereitzustellen. Ich tendiere dazu, das "Revealing Module"-Muster (siehe den ersten Link oben) zu verwenden, um Zugriff auf die Teile zu ermöglichen, die ich außerhalb meines Moduls benötige.

Indem Sie Ihre Objekte außerhalb der DOMReady-Funktion definieren und auf irgendeine Weise auf sie verweisen, ermöglichen Sie es dem Browser, mit der Verarbeitung Ihres JavaScripts zu beginnen, was das Benutzererlebnis potenziell beschleunigt. Es macht den Code auch flexibler, da Sie Dinge verschieben können, ohne sich Gedanken darüber machen zu müssen, weitere DOMReady-Funktionen zu erstellen, wenn Sie Dinge verschieben.

Sie werden wahrscheinlich immer noch eine DOMReady-Funktion verwenden, selbst wenn Sie Ihre Backbone-Objekte an anderer Stelle definieren. Der Grund dafür ist, dass viele Backbone-Anwendungen den DOM auf irgendeine Weise manipulieren müssen. Dafür müssen Sie warten, bis der DOM bereit ist, also müssen Sie die DOMReady-Funktion verwenden, um Ihre Anwendung zu starten, nachdem sie definiert wurde.

Sie finden viele Beispiele dafür im Web, aber hier ist eine sehr grundlegende Implementierung, die sowohl ein Modul als auch die DOMReady-Funktion verwendet:

// "MyApp" als ein offenlegendes Modul definieren

MyApp = (function(Backbone, $){

  var View = Backbone.View.extend({
    // Hier passiert etwas  
  });

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

})(Backbone, jQuery);

// "MyApp" in DOMReady ausführen

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

14voto

joidegn Punkte 1068

Als kleine Randnotiz, das Senden von $ als Argument an eine anonyme Funktion macht $ lokal für diese Funktion, was eine kleine positive Leistungsimplikation hat, wenn die $-Funktion häufig aufgerufen wird. Dies liegt daran, dass JavaScript zuerst den lokalen Bereich nach Variablen durchsucht und dann bis zum Fensterbereich durchläuft (wo $ normalerweise vorhanden ist).

9voto

ThiefMaster Punkte 297146

Es stellt sicher, dass Sie immer $ innerhalb dieses Closures verwenden können, auch wenn $.noConflict() verwendet wurde.

Ohne dieses Closure müssten Sie die ganze Zeit jQuery anstelle von $ verwenden.

4voto

Andrew Brock Punkte 1354

Es dient dazu, einen potenziellen Konflikt mit der $-Variable zu vermeiden. Wenn eine andere Stelle eine Variable namens $ definiert, könnte Ihr Plugin die falsche Definition verwenden

Verweisen Sie für weitere Details auf http://docs.jquery.com/Plugins/Authoring#Getting_Started

3voto

Andrew Punkte 15913

Beide verwenden.

Die selbstaufrufende Funktion, in der Sie jQuery übergeben, um Bibliothekskonflikte zu verhindern und sicherzustellen, dass jQuery verfügbar ist, wie Sie es mit $ erwarten würden.

Und die .ready()-Verknüpfungsmethode, die erforderlich ist, um JavaScript nur nach dem Laden des DOM auszuführen:

(function($) {
    $(function(){
          //fügen Sie hier den Code ein, der auf das Laden der Seite warten muss
    });

    //und der Rest des Codes hier
})(jQuery);

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X