2010-04-26 3 views
14

Nachdem ich etwas über das Modulmuster gelesen habe, habe ich ein paar Möglichkeiten gesehen, die Eigenschaften, die Sie veröffentlichen möchten, zurückzugeben.JavaScript Modul Pattern - Was ist mit der Verwendung von "Return this"?

Eine der gebräuchlichsten Methoden besteht darin, Ihre öffentlichen Eigenschaften und Methoden innerhalb der "return" -Anweisung zu deklarieren, abgesehen von Ihren privaten Eigenschaften und Methoden. Ein ähnlicher Weg (das "Aufdecken" -Muster) besteht darin, einfach Verweise auf die Eigenschaften und Methoden anzugeben, die öffentlich sein sollen. Zu guter Letzt bestand eine dritte Technik darin, ein neues Objekt innerhalb Ihrer Modulfunktion zu erstellen, dem Sie Ihre neuen Eigenschaften zuweisen, bevor Sie das Objekt zurückgeben. Dies war eine interessante Idee, erfordert jedoch die Erstellung eines neuen Objekts.

Also dachte ich, warum nicht einfach this.propertyName verwenden, um Ihre öffentlichen Eigenschaften und Methoden zuzuweisen, und schließlich return this am Ende verwenden? Dieser Weg scheint mir viel einfacher, da Sie private Eigenschaften und Methoden mit der üblichen Syntax var oder function erstellen können, oder verwenden Sie die this.propertyName Syntax, um Ihre öffentlichen Methoden zu deklarieren.

Hier ist die Methode Ich schlage:

(function() { 

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

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

return this; 

})(); 

es irgendwelche Vor/Nachteile der oben beschriebenen Methode zu verwenden? Was ist mit den anderen?

+5

Haben Sie überlegt, was genau "das" ist? Wo fügen Sie Ihre publicMethode hinzu? –

Antwort

30

Ihre Funktion hat keinen Objektkontext, daher verweist this in diesem Fall auf das globale Objekt window. Jede Eigenschaft, die Sie this zuweisen, verunreinigt automatisch den globalen Namespace.

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

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

})(); 

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

Sie können ein Objekt explizit übergeben, um zu ermitteln, welcher Kontext verwendet werden soll.

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() 

, die Sie in etwas anderen Stil schreiben:

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

Und wir kamen zu an already discussed pattern. Weitere Informationen finden Sie in Dustins Artikel unter Scoping anonymous functions.

+0

Vielen Dank. Ich war mir des Verhaltens von "diesem" in anonymen Funktionen nicht bewusst. –

+0

Es hat nichts damit zu tun, dass die Funktion anonym ist. Es hat damit zu tun, wie die Funktion (jede Funktion, die mit einer Funktionsdeklaration oder einem Funktionsausdruck erzeugt werden könnte) aufgerufen wird. Wenn Sie eine Funktion aufrufen, die in einer Variablen "f" gespeichert ist (z. B. definiert durch die Funktionsdeklaration 'function f() {}' oder über einen Funktionsausdruck, der einer Variablen zugewiesen ist: 'var f = function() {};') Mit dem Ausdruck 'f()' wird 'this' immer das globale Objekt sein. –

+0

@Tim Down: Danke für Ihre Bemerkung. Ich habe meine Antwort korrigiert. –

4

Ich würde den Stil empfehlen, wo Sie Ihre öffentlichen Eigenschaften und Methoden zu einem anonymen Objekt hinzufügen, das Sie dann zurück:

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

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

nun ja, außer du gibst etwas zurück, das sofort weggeworfen wird. –

+0

Ich bin gespannt was Jason meint. Welche Probleme ergeben sich aus der Verwendung des anonymen Objekts als Rückgabe? Dies schien die beste der Techniken zu sein, auf die ich stieß, wenn ich das Modulmuster verwendete. –

+0

Ich denke, Jason bezieht sich auf den Code, der weggelassen oder abgeleitet wurde, da wir ein Modulmuster diskutierten. Ich werde mein Beispiel aktualisieren. –

2

wenn Sie möchten, Methoden veröffentlichen, dann etwas tun:

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

Eine andere Möglichkeit ist, die diese Referenz insgesamt zu vermeiden. Definieren Sie eine Funktion, die stattdessen ein anonymes Objekt erstellt und zurückgibt.

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

Revealing Module Muster:

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}); 

Auch, wenn Sie Methode-Chaining benötigen:

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()); 

Es gibt auch viel mehr Möglichkeiten, und Sie können Ihre Module auch protagonize .

Verwandte Themen