2010-04-26 9 views
14

Después de leer un poco sobre el patrón del módulo, he visto algunas formas de devolver las propiedades que desea que sean públicas.Patrón de módulo de JavaScript: ¿qué hay de usar "devolver esto"?

Una de las maneras más comunes es declarar sus propiedades y métodos públicos directamente dentro de la declaración de "devolución", además de sus propiedades y métodos privados. De forma similar (el patrón "Revelador") es proporcionar referencias simples a las propiedades y métodos que desea que sean públicos. Por último, una tercera técnica que vi fue crear un nuevo objeto dentro de la función del módulo, al que asignas tus nuevas propiedades antes de devolver dicho objeto. Esta fue una idea interesante, pero requiere la creación de un nuevo objeto.

Así que estaba pensando, ¿por qué no simplemente usar this.propertyName para asignar sus propiedades y métodos públicos, y finalmente usar return this al final? De esta manera me parece mucho más simple, ya que puede crear propiedades y métodos privados con la sintaxis var o function, o usar la sintaxis this.propertyName para declarar sus métodos públicos.

aquí está el método que estoy sugiriendo:

(function() { 

var privateMethod = function() { 
    alert('This is a private method.'); 
} 

this.publicMethod = function() { 
    alert('This is a public method.'); 
} 

return this; 

})(); 

¿Hay ventajas/desventajas de utilizar el método anterior? ¿Qué hay de los demás?

+5

¿Has considerado qué es exactamente 'esto'? ¿Dónde está agregando su publicMethod? –

Respuesta

30

Su función no tiene contexto de objeto, por lo que this referencias al objeto global window en este caso. Cada propiedad que asigne a this contamina automáticamente el espacio de nombres global.

(function() { 
    console.log(this == window); // true 

    this.publicMethod = function() { 
     alert('This is a public method.'); 
    } 

})(); 

console.log(publicMethod); // function() 

Puede pasar explícitamente un objeto para indicar qué contexto usar.

var MYAPP = {}; 

(function() { 
    // 'this' will now refer to 'MYAPP' 
    this.publicMethod = function() { 
     alert('This is a public method.'); 
    } 
}).call(MYAPP); 

console.log(publicMethod); // undefined 
console.log(MYAPP.publichMethod); // function() 

que se puede escribir en un tanto otro estilo:

var MYAPP = (function(my) { 
    var my; 
    ⋮ 
    return my; 
})(MYAPP); 

y llegamos a an already discussed pattern. Para obtener más detalles, consulte el artículo de Dustin en Scoping anonymous functions.

+0

Muchas gracias. No estaba al tanto del comportamiento de "esto" dentro de las funciones anónimas. –

+0

No tiene nada que ver con que la función sea anónima. Tiene que ver con cómo se llama a la función (cualquier función, que podría crearse con una declaración de función o una expresión de función). Si llama a una función almacenada en una variable 'f' (por ejemplo, definida por la función declaración' función f() {} 'o mediante una expresión de función asignada a una variable:' var f = function() {}; ') utilizando la expresión 'f()', 'this' siempre será el objeto global. –

+0

@Tim Down: gracias por su comentario. Corregí mi respuesta. –

4

Yo recomendaría el estilo donde se agrega sus propiedades y métodos públicos de un objeto anónimo que luego regrese:

var myModule = (function() { 
    function privateMethod() { ... } 
    function publicMethod() { ... } 

    return { publicMethod: publicMethod }; 
})(); 
+0

Bueno, sí, excepto que está devolviendo algo que de inmediato se descarta. –

+0

Tengo curiosidad sobre lo que Jason quiere decir. ¿Qué problemas surgen del uso del objeto anónimo como devolución? Esta parece ser la mejor de las técnicas que encontré, cuando uso el patrón del módulo. –

+0

Creo que Jason se refiere al código que se omitió o dedujo, ya que estábamos discutiendo un patrón de Módulo. Actualizaré mi ejemplo. –

2

si desea publicar métodos, y luego hacer algo como:

var export = (function() { 

var privateMethod = function() { 
    alert('This is a private method.'); 
} 
var export = {}; 

export.publicMethod = function() { 
    alert('This is a public method.'); 
} 

return export; 

})(); 
2

Otra opción es evitar el esta referencia por completo. Defina una función que crea y devuelve un objeto anónimo en su lugar.

function makeThing(someAttribute) { 
    var privateVariable = 42; 

    function someMethod() { 
    return privateVariable; 
    } 

    return { 
    "publicMethodName": someMethod, 
    "getAttribute": function() { 
     return someAttribute; 
    } 
    }; 
} 

var thing = makeThing(99); 
thing.publicMethodName(); 
thing.getAttribute(); 
1

los diseños del módulo revelador:

var m1 = (function(){ return {method: mthod} })(); 
var m2 = new function Singleton(){ return {method: mthod} }; 
var m3 = ({}).prototype = {method: method}; 
var m4 = ({}).prototype = (function(){ ... })(); 
var m5 = (function(){}).prototype = {} || (function(){ ... })(); 

var m6 = (function(extendee){ 
    return extendee.prototype = {attr3: 'attr3'}; 
})({currentAttr1: 1, currentAttr2: 2}); 

Además, si usted necesita método en cadena:

var m = (function(){}).prototype = (function(){ 
    var thus = m; // this 
    console.log('m this-------', thus); 

    function fn(){ 
     console.log('fn', thus); 
     return thus; 
    } 
    function f(){ 
     console.log('f', thus); 
     return 'poop'; 
    } 

    return {f: f, fn: fn}; 
})(); 

console.log('M:', m, 'm.fn', m.fn(), 'm.fn.f', m.fn().f()); 

También hay mucho más formas, y se puede protagonizar sus módulos, así .

Cuestiones relacionadas