2010-01-04 7 views
5

Ich bevorzuge funktionale OOP-Stil für meinen Code (ähnlich dem Modulmuster), weil es mir hilft, das "neue" Schlüsselwort und alle Probleme mit dem Geltungsbereich von "diesem" Schlüsselwort zu vermeiden Rückrufe.Frage zum funktionalen OOP-Stil in JavaScript

Aber ich habe ein paar kleinere Probleme damit zu tun. Ich möchte den folgenden Code verwenden, um eine Klasse zu erstellen.

namespace.myClass = function(){ 
    var self = {}, 
     somePrivateVar1; 

    // initialization code that would call 
    // private or public methods 
    privateMethod(); 
    self.publicMethod(); // sorry, error here 

    function privateMethod(){} 

    self.publicMethod = function(){}; 

    return self; 
} 

Das Problem ist, dass ich öffentliche Methoden aus meinem Initialisierungscode nicht aufrufen kann, da diese Funktionen noch nicht definiert sind. Die offensichtliche Lösung wäre, eine Init-Methode zu erstellen und sie vor der "return self" -Zeile aufzurufen. Aber vielleicht kennen Sie eine elegantere Lösung?

Auch, wie behandeln Sie normalerweise Vererbung mit diesem Muster? Ich benutze den folgenden Code, aber ich würde gerne Ihre Ideen und Vorschläge hören.

namespace.myClass2 = function(){ 
    var self = namespace.parentClass(), 
     somePrivateVar1;    

    var superMethod = self.someMethod; 
    self.someMethod = function(){ 
    // example shows how to overwrite parent methods 
    superMethod(); 
    }; 

    return self; 
} 

Bearbeiten. Für diejenigen, die Frage, was die Gründe für die Wahl dieses Stils der OOP sind, können Sie folgende Fragen prüfen können:

+0

Es ist generell eine _bad_ Idee, die Techniken einer Sprache nicht zu verwenden. Das heißt, Sie sollten 'new' nicht umgehen, das ist genau so, wie es in Javascript gemacht wird und es ist wahrscheinlich der beste Weg _in dieser speziellen Sprache_. –

+0

Warum können Sie nicht einfach die Methoden oben definieren, bevor Sie versuchen, sie aufzurufen? –

+0

Gs, ich denke, dass die Verwendung von Schließungen zum Erstellen von Objekten mit privaten Mitgliedern eine Technik ist, die von einer Sprache gegeben wird. Sogar Douglas Crockford tritt dafür ein. Ich habe auch vorher einige Leistungstests gemacht, und für eine kleine Anzahl von Objekten spielt es keine Rolle. (http://valums.com/b/) Aber für mich macht es einen Code sauberer. –

Antwort

0

ich mit fast jedem Kommentar zustimmen oder so weit vorgesehen Antwort, aber weiter Tims Antwort einen Schritt zu nehmen - er die Frage, warum Sie eine Methode aufrufen wollen würde, bevor sie definiert wurde, bot aber trotzdem eine Lösung, während ich Sie sollte vor dem definieren nicht Aufruf vorschlagen würde (ich weiß nicht, jeder Sprache, in der Definition es vor Aufruf einer Methode oder zumindest erklären, gute Praxis betrachtet), so wie etwa:

namespace.myClass = function(){ 
    //declare private vars (and self) first 
    var self = {}, 
     somePrivateVar1; 

    //then declare private methods 
    function privateMethod(){} 

    //then public/privileged methods 
    self.publicMethod = function(){}; 

    // THEN (and only then) add your 
    // initialization code that would call 
    // private or public methods 
    privateMethod(); 
    self.publicMethod(); // no error any more 

    //then return the new object 
    return self; 
} 

Gibt es einen bestimmten Grund, warum dies nicht für Sie arbeiten würde?

+0

Danke, das wird gut funktionieren, aber ich würde es vorziehen, den Konstruktor oben zu lassen, da es sehr häufig ist, und ich möchte Gewohnheiten von anderen Programmierern nicht brechen. –

1

Mehr Fragen kommen zu mir, wie, warum Sie möchte den Operator new vermeiden und warum Sie Funktionen aufrufen möchten, bevor sie definiert sind. Aber abgesehen davon, wie wäre es mit etwas wie dem folgenden?

namespace.myClass = function(){ 
    var somePrivateVar1; 
    var self = {}; 

    // initialization code that would call 
    // private or public methods 
    privateMethod(); 
    publicMethod(); 

    function privateMethod(){} 
    function publicMethod(){} 

    self.publicMethod = publicMethod; 
    return self; 
} 
+0

Danke, eines der Probleme mit diesem Ansatz besteht darin, dass Sie keinen Verweis auf ein aktuelles Objekt in Ihrer Klasse haben. Aber in meinem Beispiel war es möglich, ein Objekt selbst an eine andere Funktion zu übergeben. someFunctionThatRegistersAnObject (self); –

+0

Ich habe versucht, Ihre Antwort zu bewerten, aber stackoverflow zeigt einen Fehler "Wählen Sie zu alt, um geändert zu werden, wenn diese Antwort nicht bearbeitet wird". Ist es ein Fehler? –

+0

@valums: Die Antwort wurde geändert, um Ihren Kommentar zu adressieren. Nicht sicher über SO-Fehler, aber Sie sollten in der Lage sein, Ihre Abstimmung jetzt zu ändern Ich habe die Antwort bearbeitet. –

0

Dies ist die Lösung, die ich in der Frage erwähnt habe. Ihre Kommentare sind willkommen.

namespace.myClass = function(){ 
    var self = {}, 
     somePrivateVar1; 

    function init(){ 
    privateMethod(); 
    self.publicMethod(); 
    } 

    function privateMethod(){} 
    self.publicMethod = function(){}; 

    init(); 
    return self; 
} 
+1

Das wird funktionieren, und wenn Sie verpflichtet sind, Initialisierungscode an der Spitze zu haben, bevor Sie eine Ihrer Methoden deklarieren, wäre der einzige Weg zu gehen, soweit ich das beurteilen konnte. Mein einziger Kommentar ist, dass dies nicht "elegant" ist, was Sie verlangt haben, aber meine * persönliche * Meinung ist, dass Ihre Kriterien dafür, wie die Methode aussehen soll, nicht elegant sind - also innerhalb dieses Kriteriums, Was Sie dort haben, ist wahrscheinlich die beste Lösung. – Graza

2

können Sie Zet.js Bibliothek verwenden, die Sie mit erklären Klassen in der Art und Weise helfen Sie wollen.