2008-10-09 2 views
9

Je suis curieux de savoir s'il existe des bonnes pratiques concernant JQuery lors de la construction de blocs de code encapsulés.JQuery JavaScript Design: fonction auto-exécutable ou littéral d'objet?

Généralement, lorsque je construis une page, j'aime encapsuler les fonctions utilisées dans cette page à l'intérieur d'un objet. Cela me permet une certaine encapsulation lors de la construction d'applications. Il n'y a rien que je déteste plus que de voir un fichier JavaScript avec un tas de cette

function doSomethingOnlyRelevantOnThisPage() { 
    // do some stuff 
} 

I cela fait désordre pour la conception, et n'encapsule pas vraiment fonctionnalité bien.

Généralement dans de nombreux cadres, il existe une norme qui est utilisée pour effectuer cette encapsulation.

En Mootools ils sont favorables à l'objet Notation littérales:

var Site = {   
    // properties and methods 
} 

En YUI ils favorisent l'auto exécution notation Fonction:

(function() { // properties and methods })() 

La bonne chose à propos du deuxième exemple est qu'une fermeture est créée , vous permettant ainsi de définir des propriétés et des méthodes privées.

Ma question est la suivante: Est-ce que les aficionados de JQuery ont des bonnes pratiques pour créer ces structures proprement encapsulées? Quelle est la raison d'être de leur utilisation?

Répondre

9

Depuis que je travaille avec jQuery depuis un moment maintenant, j'ai décidé d'un modèle standard qui fonctionne bien pour moi.

Il s'agit d'une combinaison du modèle de module YUI avec un peu de modèle de plugin jQuery mélangé. . Nous avons fini par utiliser le modèle de fermeture auto-exécutable.Cela est bénéfique de plusieurs façons:

  1. Il conserve le code à un minimum
  2. Il applique la séparation du comportement de la présentation
  3. Il fournit une fermeture qui empêche les conflits de noms

C'est ce que il ressemble à:

;(function($) {   
    var myPrivateFunction = function() { 
    }; 

    var init = function() { 
     myPrivateFunction(); 
    }; 

    $(init); 
})(jQuery); 

Nous avons réalisé que l'attribution du résultat de l'exécution de la fonction, similaire au modèle de module YUI, expose le code potentiellement appelé depuis le code de présentation. Nous voulons empêcher cela, donc ce modèle convient.

Bien sûr, nous aurions pu écrire la méthode init en ligne, sans définir de variable pour la fonction. Nous avons convenu que la définition explicite de la fonction init rendait le code plus clair aux lecteurs. Que se passe-t-il si nous voulons partager des fonctions entre des pages/des fichiers js externes? Nous branchons simplement le mécanisme existant que jQuery fournit pour étendre l'objet jQuery lui-même - la fonction extend. Si les fonctions sont statiques, nous utilisons $ .extend, et si elles fonctionnent sur un ensemble encapsulé, nous utilisons la fonction $ .fn.extend.

Espérons que cela aide quelqu'un.

+1

Je continue à voir ce modèle, mais j'aspire à un exemple plus complet - j'ai une page avec quelques éléments interactifs distincts et assez impliqués dont la logique devrait être encapsulée indépendamment les uns des autres. Des suggestions pour organiser le code dans ce genre de situation? Utiliser $ .fn.extend pour chaque pièce d'interface utilisateur différente semble contre-intuitif. –

+0

Je ne recommanderais certainement pas d'étendre la fonction jquery à moins que vous n'écriviez un plugin - donc quelque chose qui est réutilisable dans de nombreuses pages. Dans mon cas, je diviserais ma fonctionnalité en ses parties distinctes, créant une fonction auto-exécutable pour contenir cette logique dans sa propre fermeture. Tout code partagé peut ensuite être attaché à jQuery lui-même via $ .extend, ce qui vous permettrait d'avoir des fonctions d'assistance qui ne nécessitent pas le contexte d'un élément pour fonctionner. –

+0

Très bon article sur l'expression de fonction invoquée immédiatement (IIFE) http://benalman.com/news/2010/11/immediately-invoked-function-expression/ – stormwild

1

Je suis habituellement le modèle prototype:

MyFunction = function(param1, param2) 
{ 
    this.property1 = param1; 
    // etc. 
} 

MyFunction.prototype = 
{ 
    memberOne: function(param1) 
    { 
     // ... 
    }, 

    memberTwo: function(param2) 
    { 
    } 
} 

Vous obtenez quelque chose d'un « constructeur » (la fonction elle-même) et encapsulées « méthodes » et « champs ».

Il est plus facile pour quelqu'un qui est utilisé pour les langues basés sur les classes :)

+0

Mais cela n'est utile que si vous prévoyez d'encapsuler l'état dans les objets. Vous devrez appeler nouveau sur ces objets pour créer des instances. Dans mon cas, ils se comporteraient plutôt comme une classe statique en termes d'OO. –

+0

Vrai, vrai ... dans ce cas je préférerais des fonctions anonymes auto-exécutables. –

3

J'utilise YUI et jQuery lors du développement (widgets YUI et quelques fonctions de commodité, sélecteurs jQuery et javascript « extensions »), et général javascript modèle J'utilise est la suivante:

/*global YAHOO, $ */ 

// Create the public-scope accessable namespace for this page 
YAHOO.namespace('Project'); 

YAHOO.Project.page = function() { 
    // Private members 

    var self = {}; 

    // Public members 
    var pub = {}; 

    pub.init = function() { 

    }; 

    return pub; 
}(); 

// When the DOM is loaded, initialize this module 
$(document).ready(YAHOO.Project.page.init); 

maintenant clairement, vous pouvez supprimer le YAHOO.namespace() appeler si vous ne voulez pas utiliser YUI, mais c'est les grandes lignes. Il utilise la notation littérale d'objet, mais vous permet également de définir des propriétés et des méthodes privées. N'oubliez pas que lorsque vous appelez des membres privés ou que vous référencez des variables privées pour les référencer comme self.funcName(). Vous pouvez les définir en dehors de l'objet self, mais alors vous obtenez un mismash partout dans votre objet, où vous essayez de comprendre si size_of() est une méthode privée ou définie globalement ailleurs.

Questions connexes