Cómo utilizar el patrón de módulo revelador en JavaScript

78

Me encontré con esta publicación: Patrón de módulo revelador de JavaScript . Me gustaría usar esto en mi proyecto.

Imaginemos que tengo una función abc y la llamo en mi archivo JavaScript principal.

¿Este patrón hace que las cosas sean diferentes? ¿Alguien puede mostrarme un ejemplo básico de este patrón?

theJava
fuente
3
Para mí, este artículo es la mejor explicación que he visto hasta ahora.
Mohammad Sepahvand
2
¿Por qué usar el patrón de módulo revelador, cuando puede usar el patrón de módulo definitivo? github.com/tfmontague/definitive-module-pattern
tfmontague

Respuestas:

98

Un pequeño ejemplo:

var revealed = function(){
   var a = [1,2,3];
   function abc(){
     return (a[0]*a[1])+a[2];
   }

   return {
      name: 'revealed',
      abcfn: abc
   }
}();

en la función anónima que se inicia para dar revealedun valor, ay abcson privados para esa función. Lo que devuelve la función es un objeto literal con una namepropiedad y una abcfnpropiedad, que es una referencia a abc function. El abc functionusa la variable privada a. Todo esto se puede hacer gracias al uso de cierres (todo lo que está dentro del alcance de una función puede ser referenciado por todo lo demás en esa misma función).

Uso revelado:

alert(revealed.name);    //=> 'revealed'
alert(revealed.abcfn()); //=> 5 (1*2+3)
KooiInc
fuente
8
¡Este patrón cambió mi vida!
klewis
6
Sé que esto es antiguo, pero al valor de retorno de abc () le falta un paréntesis =]
Fillip Peyton
¿Por qué usar el patrón de módulo revelador, cuando puede usar el patrón de módulo definitivo? github.com/tfmontague/definitive-module-pattern
tfmontague
¿Cómo creo una nueva instancia de Revelado?
Neon Warge
@NeonWarge: no es así. La función no es un constructor. Devuelve un objeto literal, en el que ay abcestán cerrados.
KooiInc
23

DC = Douglas Crockford
RMP = Revelando el patrón del módulo

La diferencia entre DC y RMP es principalmente organizativa / legible

¿El ejemplo se presenta en el artículo mismo? Y qué preguntas exactamente porque esas cosas no tienen nada que ver con los archivos sino con los cierres.

Pones todo en un cierre (función) y expones solo la parte que deseas que sea accesible. La diferencia entre el estilo DC y el RMP es que en el primero las funciones se definen en diferentes lugares mientras que en el RMP siempre se definen en el mismo lugar y luego se revelan en el literal de objeto público .

Entonces, en DC y RMP tienes:

  • cierre que permite definir partes privadas (variables y funciones)
  • parte privada
  • resultado público que define la funcionalidad y las variables públicamente visibles (estado)

Estos dos patrones solo se diferencian en la legibilidad. En el caso de DC, no siempre puede saber dónde se definirá cierta funcionalidad, pero en el RMP siempre sabe que todo está en la parte privada.

Robert Koritnik
fuente
1
No es cierto que DC y RMP sean lo mismo, los dos son muy diferentes cuando se trata de herencia. Ver stackoverflow.com/questions/21925720/… por ejemplo
I-Lin Kuo
6

El método llamado por el autor "patrón de Douglas Crockford para crear objetos" es en realidad el patrón de módulo que fue desarrollado principalmente por Richard Cornford et al . Ver http://groups.google.com/group/comp.lang.javascript/msg/9f58bd11bd67d937

En cuanto a ejemplos, hay muchos. Lea el siguiente artículo y siga algunos de los enlaces: http://peter.michaux.ca/articles/module-pattern-provides-no-privacy-at-least-not-in-javascript-tm

RobG
fuente
Rehice mi publicación, avíseme si todavía hay algún problema :)
Alex
Es interesante cómo estas cosas se transforman con el tiempo. La versión "reveladora" ha sido utilizada por David Mark (de la fama de MyLibrary ) durante algún tiempo, no tengo problemas con la versión "no reveladora", así que la uso. :-)
RobG
1

Me gusta usar una mezcla del patrón de módulo revelador con el patrón singleton para poder mantener un código estructurado con los beneficios del patrón de módulo:

var MyFunction = function(){

    var _ = {
       Init: function(){
          _.Config.foo = "hello world";
       },
       Config:{
          foo:null
       },
       ShowAlert:function(){
          alert(_.Config.foo);
       }
    }

    return {
        Init: _.Init,
        ShowAlert: _.ShowAlert
    };
}();

MyFunction.Init();
MyFunction.ShowAlert();

Escribí más información sobre esto en mi blog:

http://curtistimson.co.uk/js/mixing-revealing-module-and-singleton-javascript-patterns/

Brusco
fuente
1

Solo quiero agregar: con este patrón es bueno pasar las dependencias globales como argumentos / parámetros para que sean explícitos. No tiene que hacerlo, pero esto deja muy claro qué necesita su módulo desde el primer vistazo. P.ej:

var myModule = (function ($, loadModule) {
  "use strict";
})(jQuery, load);

En este ejemplo, puede ver de inmediato en la primera línea que su módulo usa jQuery y algún otro módulo responsable de cargar la funcionalidad.

Maria blair
fuente
0

Para el código fuera del módulo, hay poca diferencia. En los 3 casos de ese artículo, los métodos se denominan de la misma manera. Pero la estructura del módulo en sí es internamente diferente.

El patrón de módulo de Crockford y lo que ellos llaman el "patrón de módulo revelador" son prácticamente lo mismo, estructuralmente. La única diferencia es que primero asignan el método a una var local para que sea más legible. Pero realmente no tiene nada de especial, y tienes algunos ejemplos en tu enlace.

Alex Wayne
fuente
El objeto devuelto por el patrón de módulo revelador no se comporta como el patrón de módulo de Douglas Crockford con respecto a la anulación (consulte la advertencia de Addy Osmani en addyosmani.com/resources/essentialjsdesignpatterns/book/… ).
I-Lin Kuo
0

El concepto básico de un Módulo Revelador es que tiene un Objectque encapsula sus datos y comportamiento:

var Module = (function(){
    var privateStuff = {};
    var publicStuff = {};

    return publicStuff;
})();

Sin embargo, existen algunas prácticas recomendadas que debe emplear al utilizar este patrón. Aquí hay un módulo (" Modulus") con algunas propiedades por motivos de demostración, que emplea algunas de estas prácticas:

function AbstractSomeClass(id) {
    this.id = id;
    return this;
}

var Modulus = (new (function SomeClass() {
    var thus = this;

    function NameClass(name){
        this.value = thus.name || name;
    }

    AbstractSomeClass.call(this, 998);

    this.name = 'Touring';
    this.name = ( new NameClass('Hofstadter') ).value;

    return {
        id: this.id,
        name: this.name
    };
})());

Observe la (new (function SomeClass(){ ... })());sintaxis. Usar newasí le permite usar la thispalabra clave dentro del cierre. Esto es útil si necesita heredar propiedades de otra clase ( AbstractSomeClass.call(this, 998);). Sin embargo, aún deberá revelar las propiedades que le gustaría tener públicas, por ejemplo:

return {
    id: this.id,
    name: this.name
};

También observe que asignamos thisa thus, lo que nos permite usar el Padre, thisdentro de una subclase que tiene su propio thisalcance ( this.value = thus.name || name;)

Una vez más, estas son solo algunas de las convenciones y mejores prácticas que se sugieren.

Cody
fuente
0

Aquí está el pequeño ejemplo de patrón de módulo revelador.

Proporciona una facilidad para declarar funciones públicas y privadas como una clase. Son los principales beneficios de estos patrones. Si no queremos exponer algunas de las funcionalidades accesibles desde globalmente, las hace privadas y el resto las hacen públicas. es el ejemplo de cómo hacer funciones públicas y privadas. Y una cosa más es un bloque de código autoejecutable.

  var Calculator = (function () {

        var num1 = 10;
        var num2=5
        var _abc = function () {
            return num1 - num2;
        };

        var _mulFunc = function () {
            return num1 * num2;
        };

        var _divFunc = function () {
            return num1/num2;
        };

        return {
           //public scope
            abc: _abc,
            mulFunc:_mulFunc
         };

    })();

alerta (Calculadora.abc ()); devuelve 5

alerta (Calculator.mulFunc ()); devuelve 50

Y __divFunc () no será accesible ya que está en un ámbito privado. Podemos acceder solo a aquellas funciones que se declaran dentro del objeto de retorno, ya que es una representación de función pública

Sheo Dayal Singh
fuente