2008-10-09 17 views
9

Tengo curiosidad por saber si hay mejores prácticas relacionadas con JQuery al construir bloques de código encapsulados.JQuery JavaScript Design: ¿Función autoejecutable u objeto literal?

Generalmente, cuando construyo una página me gusta encapsular las funciones utilizadas dentro de esa página dentro de un objeto. Esto me permite un poco de encapsulación cuando construyo aplicaciones. No hay nada que odie más que ver a un archivo JavaScript con un montón de este

function doSomethingOnlyRelevantOnThisPage() { 
    // do some stuff 
} 

que esto lo convierte en el diseño desordenado, y en realidad no se encapsulan una funcionalidad muy bien.

Comúnmente en muchos marcos, hay un estándar que se utiliza para realizar esta encapsulación.

En Mootools Favorecen la notación literal de objetos:

var Site = {   
    // properties and methods 
} 

En YUI Favorecen el Ser se ejecuta la función de notación:

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

Lo bueno del segundo ejemplo es que se crea un cierre , lo que le permite definir propiedades y métodos privados.

Mi pregunta es esta: ¿Alguno de los aficionados a JQuery tiene alguna de las mejores prácticas para crear estas estructuras perfectamente encapsuladas? ¿Cuál es la razón de su uso?

Respuesta

9

Desde hace un tiempo que trabajo con jQuery, me he decidido por un patrón estándar que funcione bien para mí.

Es una combinación del patrón del módulo YUI con un poco del patrón de plugin jQuery mezclado en. . Terminamos usando el patrón de cierre autoejecutable.Esto es beneficioso en varias formas:

  1. Mantiene código para un mínimo de
  2. Se impone la separación de la conducta de la presentación
  3. Proporciona un cierre que evita los conflictos de nombres

Esto es lo parece que:

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

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

    $(init); 
})(jQuery); 

Nos dimos cuenta de que asignando el resultado de la ejecución de la función, similar al patrón del módulo YUI, expone el código que podría ser llamado desde el código de presentación. Queremos evitar esto, por lo que este patrón se ajusta.

Por supuesto, podríamos haber escrito el método init en línea, sin definir una variable para la función. Acordamos que definir explícitamente la función init hizo que el código fuera más claro para los lectores.

¿Qué ocurre si queremos compartir funciones entre páginas/archivos js externos? Simplemente nos conectamos con el mecanismo existente que jQuery proporciona para extender el objeto jQuery en sí: la función extender.

Si las funciones son estáticas, usamos $ .extend, y si funcionan sobre un conjunto envuelto, usamos la función $ .fn.extend.

Espero que esto ayude a alguien.

+1

Sigo viendo este patrón, pero anhelo un ejemplo más completo: tengo una página con algunos elementos interactivos distintos y bastante complicados cuya lógica debe encapsularse unos de otros. ¿Alguna sugerencia para organizar el código en ese tipo de situación? Usar $ .fn.extend para cada pieza de UI diferente parece contra intuitivo. –

+0

Definitivamente no recomendaría extender la función jquery a menos que esté escribiendo un complemento, por lo que es algo que se puede volver a usar en muchas páginas. En su caso, rompería mi funcionalidad en sus distintas partes, creando una función autoejecutable para contener esa lógica en su propio cierre. Cualquier código compartido puede adjuntarse a jQuery a través de $ .extend, lo que le permitiría tener funciones de ayuda que no requieren el contexto de un elemento para funcionar. –

+0

Muy buen artículo sobre Expresión de función invocada inmediatamente (IIFE) http://benalman.com/news/2010/11/immediately-invoked-function-expression/ – stormwild

1

por lo general siguen el patrón prototipo:

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

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

    memberTwo: function(param2) 
    { 
    } 
} 

Se obtiene algo un "constructor" (la función en sí) y "métodos" encapsulados y "campos".

Es más fácil para alguien que está acostumbrado a lenguajes orientados a objetos basados ​​en la clase :)

+0

Pero esto solo es útil si planea encapsular el estado dentro de los objetos. Tendría que llamar a new en estos objetos para crear instancias. En mi caso, se comportarían más como una clase estática en términos OO. –

+0

Cierto, cierto ... en este caso preferiría las funciones anónimas autoejecutables. –

3

utilizo Yui y jQuery en el desarrollo (widgets Yui y un par de funciones de confort, selectores de jQuery y "extensiones" javascript), y el en general Javascript plantilla que uso es la siguiente:

/*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); 

Ahora claramente, se puede quitar la YAHOO.namespace() llamada Si no desea utilizar YUI, pero ese es el esquema básico. Utiliza la notación literal del objeto, pero también le permite definir propiedades y métodos privados.

Solo recuerde que cuando llame a miembros privados o haga referencia a variables privadas para hacer referencia a ellos como self.funcName(). Puede definirlos fuera del objeto self, pero luego obtiene un mismo lugar en su objeto donde intenta averiguar si size_of() es un método privado o está definido globalmente en otro lugar.

Cuestiones relacionadas