2009-06-25 13 views
7

Nach einem wenig Javascript liest prototypical inheritance model, den Zugriff ändere ich meinen Stil aus einer Klasse von der Konstruktionbessere Art und Weise private Mitglieder in Javascript

var Some_Class = function() { 
    this.public_method = function() { 
    }; 
    (function() { 
     // constructor 
    }).call(this) 
} 

zu

var Some_Class = function() { 
    (function() { 
     // constructor 
    }).call(this) 
} 
Some_Class.prototype.public_method = function() { 
}; 

Obwohl ich verstehe, dass dies eine ist gute Praxis, aber ich darf nicht mehr auf private Methoden aus der öffentlichen Methode zugreifen

var Some_Class = function() { 
    var private_member = 'whatever'; 

    (function() { 
     // constructor 
    }).call(this) 
} 
Some_Class.prototype.public_method = function() { 
    return private_member; // not possible 
}; 

Nach here (Closure erstellte Konstruktor), dann kam ich heraus mit diesem

var Some_Class = function() { 
    var private_member = 'whatever', 

    private_method = function(_some_value) { 
     // private method implementation 
    }; 

    if(!arguments.callee.prototype.public_method) { 
     arguments.callee.prototype.public_method = function() { 
      private_method.call(this, private_method); 
     }; 
    } 

    (function() { 
     // constructor 
    }).call(this) 
} 

Doch was sind die Nachteile, dies zu tun durch einen Artikel zu lesen ?! oder gibt es eine bessere Möglichkeit, dies zu tun, wenn ich in der öffentlichen Methode auf private member zugreifen möchte?

Antwort

10

Die Verwendung von Funktionsbereichsvariablen und -schließungen zum Simulieren von privaten Variablen/Funktionen ist in der JavaScript-Community ein gut eingeführtes Idiom. Wenn die Variable wirklich privat sein soll, sehe ich keinen Nachteil in diesem Ansatz (obwohl einige behaupten, dass performanter Code auf bestimmten Browsern/Hosts darauf achten muss, wie viele Verschlüsse erstellt werden). In Ihrem Beispiel wird die private_method (und ihre Umgebung) für alle Objekte freigegeben - da Ihre public_method-Schließung nur beim ersten Erstellen des Objekts erstellt wird (und an die Prototypeigenschaft des Konstruktors gebunden wird, die den internen Prototyp des erstellten Objekts festlegt) Kette) - also ist die private_method, die verwendet wird, nur die, die das erste Mal erstellt wurde.

Hier einige Beispielcode, der veranschaulichen helfen, was los ist:

 
    var global = 1; 

    var Some_Class = function() { 
    var private_method = 'whatever'; 
    var now = ++global; 
    print("outer now: " + now); 
    private_method = function(_some_value) { 
     // private method implementation 
     print("inner now: " + now); 
    }; 

    if(!arguments.callee.prototype.public_method) { 
     arguments.callee.prototype.public_method = function() { 

      private_method.call(this, private_method); 
     }; 
    } 

    (function() { 
     // constructor 
    }).call(this) 
} 

new Some_Class().public_method(); // outer now: 2, inner now: 2 
new Some_Class().public_method(); // outer now: 3, inner now: 2 
new Some_Class().public_method(); // outer now: 4, inner now: 2 

Sind Sie sicher, das ist, was Sie wollen?

Wenn Ihre private_Methode nicht auf den Status des umschließenden Objekts verweisen muss, sehe ich wenig Nutzen darin, die Dinge so zu machen, wie Sie es tun.

Was ich in der Regel tun (wenn ich verwenden müssen ‚neue‘ mein Objekt erstellen) ist die folgende:

 
function MyClass() { 
    var private_var = 1; 
    function private_func() 
    { 

    } 
    this.public_func = function() 
    { 
    // do something 
    private_func(); 
    } 
    this.public_var = 10; 
} 

var myObj = new MyClass(); 

Der Nachteil dieses Ansatzes ist, dass jedes Mal, wenn Sie das Objekt über ‚neue‘ konstruieren Sie erstellen alle Schließungen neu. Aber wenn mein Profiler mir nicht sagt, dass diese Designauswahl optimiert werden muss, bevorzuge ich seine Einfachheit und Klarheit.

Auch sehe ich nicht den Nutzen in Ihrem Code die von folgenden Aktionen entweder:

 
    (function() { }).call(this); // call the constructor 

Warum erstellen Sie einen separaten Rahmen in Ihrem Konstruktor?

+0

danke für die Klärung, für die zweite Frage ... Ich denke, es ist wahrscheinlich, weil ich immer noch nicht sehr vertraut mit dem Objektmodell und wollte meinen Code vergleichbar mit OOP-Code in PHP/Java/andere OOP Programmiersprache – Jeffrey04

11

Meine Antwort ist eine Nicht-Antwort: Es gibt keinen eingebauten private Zugang in JavaScript, aber das ist in Ordnung, weil YAGNI. Hier ist, wie ich private Mitglieder in meinem Code machen:

function Some_Class() { 
    this._private_member = 'whatever'; 
} 

Some_Class.prototype._private_method = function() { 
}; 

Das gut genug ist.Es ist nicht wirklich wert, durch Reifen zu springen, wenn der einzige wirkliche Zweck von private ist, sich vor ... selbst zu schützen.

(das sage ich mir das Spiel mit jeder Permutation von Verschlüssen und Prototyping viele Stunden damit verbracht zu haben, so wie du bist, und sagte schließlich „schrauben, es lohnt sich nicht“.)

+0

Ich stimme zu. Das Erzwingen eines gefälschten privaten Zugriffs in Sprachen, die dies nicht unterstützen, bedeutet normalerweise UR DOING IT RONG. – Triptych

+0

@Triptych - Während ich allgemein stimme, dass, wenn Sie eine gut entworfene Sprache kämpfen müssen, um zu tun, was Sie tun möchten, dann sollten Sie Ihr Design wirklich überdenken. Aber in diesem Fall wird die Simulation des privaten Zugriffs durch Funktionsumfangvariablen und -schließungen von vielen etablierten und erfahrenen JavaScript-Programmierern als natürliche Javascript-Sprache unterstützt. –

+0

+1 ein Nebeneffekt ist all die verrückten Schließpläne neigen dazu, viele IDEs Code assistieren –

1

Wenn Sie nicht haben getan, also bereits einen Blick auf diese JavaScript Module Pattern, die Sie Zugriff auf private Methoden und Variablen aus innerhalb der öffentlichen Funktionen, etc.

+0

: DI habe darüber gelesen, nur dass aus irgendeinem Grund mag ich nicht ganz Singleton Muster und will einen alternativen Weg finden .. – Jeffrey04

0

Funktioniert mit Prototyp, nicht nur Singleton. Problem ist, wenn es Unterklasse ist, hat meine Unterklasse keinen Zugriff auf die privaten

+1

Sogar Unterklassen in Java haben keinen Zugriff auf ihre "Super" -Einheiten. – lcn

1

Echo John Kugelman: Es ist unmöglich, private Mitglieder in Javascript zu erstellen. Lebe damit. Selbst wenn Sie ein Gehäuse wie folgt erstellen:

function SomeClass() { 

    var _private = 0; 
    this.public_acessor = function() {return _private}; 
} 

Jeder Benutzer kann immer noch schreiben:

SomeClass._not_private_anymore = 1; 
SomeClass.public_acessor = function() {return this._not_private_anymore}; 

Am Ende kann man kein öffentliches Mitglied vertrauen die gleiche Sie erklärt werden. Wenn jemand Ihren Code brechen möchte, wird er es tun! Ein anderer Benutzer bricht den Code nicht, nur weil er nützlich ist.

Verwandte Themen