108 votes

Pourquoi définir une fonction anonyme et lui passer jQuery comme argument ?

Je suis en train de regarder l'excellent code de démonstration peepcode des screencasts backbone.js. Dans ce code, le code backbone est enfermé dans une fonction anonyme à laquelle on passe l'objet jQuery :

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

Dans mon propre code de base, j'ai simplement enveloppé tout mon code dans l'événement "ready" du DOM de jQuery :

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

Quel est l'intérêt/avantage de la première approche ? En procédant de cette manière, on crée une fonction anonyme qui est ensuite exécutée immédiatement, l'objet jQuery étant passé comme argument de fonction, ce qui garantit effectivement que $ est l'objet jQuery. Est-ce là le seul intérêt - garantir que jQuery est lié à '$' ou y a-t-il d'autres raisons de procéder ainsi ?

190voto

Derick Bailey Points 37859

Les deux blocs de code que vous avez montrés sont radicalement différents dans le moment et la raison de leur exécution. Ils ne s'excluent pas l'un l'autre. Ils ne servent pas le même objectif.

Modules JavaScript

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

Il s'agit d'un modèle de "module JavaScript", mis en œuvre avec une fonction à invocation immédiate.

Le but de ce code est de fournir une "modularité", une confidentialité et une encapsulation pour votre code.

L'implémentation de ceci est une fonction qui est immédiatement invoquée par l'appelant. (jQuery) entre parenthèses. L'objectif du passage de jQuery dans la parenthèse est de fournir une portée locale à la variable globale. Cela permet de réduire la quantité de frais généraux liés à la recherche de la valeur $ et permet une meilleure compression / optimisation pour les mineurs dans certains cas.

Les fonctions à invocation immédiate sont exécutées, et bien, immédiatement. Dès que la définition de la fonction est terminée, la fonction est exécutée.

La fonction "DOMReady" de jQuery

Il s'agit d'un alias de la fonction "DOMReady" de jQuery : http://api.jquery.com/ready/

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

La fonction "DOMReady" de jQuery s'exécute lorsque le DOM est prêt à être manipulé par votre code JavaScript.

Modules et DOMReady dans le code Backbone

Il est mal vu de définir votre code Backbone à l'intérieur de la fonction DOMReady de jQuery, et cela peut nuire aux performances de votre application. Cette fonction n'est pas appelée tant que le DOM n'est pas chargé et prêt à être manipulé. Cela signifie que vous attendez que le navigateur ait analysé le DOM au moins une fois avant de définir vos objets.

C'est une meilleure idée de définir vos objets Backbone en dehors d'une fonction DOMReady. Je préfère, comme beaucoup d'autres, le faire à l'intérieur d'un pattern JavaScript Module afin d'assurer l'encapsulation et la confidentialité de mon code. J'ai tendance à utiliser le pattern "Revealing Module" (voir le premier lien ci-dessus) pour donner accès aux éléments dont j'ai besoin en dehors de mon module.

En définissant vos objets en dehors de la fonction DOMReady et en fournissant un moyen de les référencer, vous permettez au navigateur de prendre de l'avance dans le traitement de votre JavaScript, ce qui peut accélérer l'expérience utilisateur. Cela rend également le code plus flexible, car vous pouvez déplacer des objets sans avoir à vous soucier de créer d'autres fonctions DOMReady lorsque vous déplacez des objets.

Vous allez probablement utiliser une fonction DOMReady, même si vous définissez vos objets Backbone ailleurs. La raison en est que de nombreuses applications Backbone doivent manipuler le DOM d'une manière ou d'une autre. Pour ce faire, vous devez attendre que le DOM soit prêt, donc vous devez utiliser la fonction DOMReady pour démarrer votre application après qu'elle ait été définie.

Vous pouvez trouver de nombreux exemples sur le web, mais voici une mise en œuvre très basique, utilisant à la fois un module et la fonction 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();
});

14voto

joidegn Points 592

En outre, l'envoi de $ en tant qu'argument d'une fonction anonyme rend $ local à cette fonction, ce qui a une petite incidence positive sur les performances si la fonction $ est souvent appelée. Cela s'explique par le fait que javascript recherche d'abord les variables dans la portée locale, puis descend jusqu'à la portée de la fenêtre (où se trouve généralement $).

8voto

ThiefMaster Points 135805

Il vous permet de toujours utiliser $ à l'intérieur de cette fermeture, même si $.noConflict() a été utilisé.

Sans cette fermeture, vous seriez supposé utiliser jQuery au lieu de $ tout le temps.

4voto

Andrew Brock Points 1003

Il s'agit d'éviter un conflit potentiel de la variable $. Si quelque chose d'autre définit une variable nommée $, votre plugin peut utiliser la mauvaise définition

Se référer à http://docs.jquery.com/Plugins/Authoring#Getting_Started pour plus de détails

3voto

Andrew Points 6859

Utilisez les deux.

La fonction auto-invoquante dans laquelle vous passez jQuery pour éviter les conflits de bibliothèques et pour vous assurer que jQuery est disponible comme vous le souhaitez avec $.

Et la méthode de raccourci .ready() est nécessaire pour exécuter le javascript uniquement après le chargement du DOM :

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

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X