Entfernen des öffentlichen Zugriffs auf Methoden für ein Objekt

8

Ich möchte ein Objekt nehmen und einige Methoden daraus entfernen.

d. Ich habe intern ein Objekt mit Getter / Setter und ich möchte externen Benutzern Zugriff darauf geben. Ich möchte nicht, dass sie Zugriff auf die Setter-Funktionen haben.

Ich möchte die ursprüngliche Objektreferenz nicht ändern, indem ich Methoden daraus entferne, sondern eine neue Objektreferenz, die auf dasselbe Objekt verweist, aber weniger Methoden enthält.

  • Wie würde ich das machen?
  • Ist das ein Design-Muster?
  • Gibt es bekannte Lösungen für diese Art von Problemen?

Ich habe eine Implementierung dieser Funktion

%Vor%

Siehe Live-Beispiel , _.each _.bindAll

Für alle beabsichtigten Zwecke sollte das zurückgegebene Objekt dasselbe wie das ursprüngliche Objekt sein, außer dass einige der Methoden nicht mehr vorhanden sind. Die interne this -Referenz darf keine der Funktionen unterbrechen. Die Prototypketten sollten nicht brechen.

  • Was wäre ein intuitiver Name für eine solche Funktion?
  • Gibt es irgendwelche Fallstricke bei meiner derzeitigen Implementierung, die mir bewusst sein sollten?
Raynos 20.02.2011, 15:51
quelle

9 Antworten

5

Was Sie tun sollten, ist ein Fassadenmuster , das nur die Methoden enthält, die Sie behalten möchten und Delegation Pattern , um diese Methoden an eine Instanz des ursprünglichen Objekts zu delegieren. Mit der reichen Reflexion, die mit Javascript verfügbar ist, sollten Sie in der Lage sein, diese Fassaden relativ einfach zu generieren.

    
Jarrod Roberson 23.02.2011, 17:38
quelle
2

Mindestens ein Problem bei Ihrer Implementierung ist die Abhängigkeit von obj.constructor . Die Eigenschaft constructor ist notorisch nicht schreibgeschützt und kann leicht durcheinander gebracht werden. Betrachten Sie das folgende Muster, das eine ziemlich übliche Art ist, Klassen in Javascript zu definieren:

%Vor%

Ich denke, der Weg dahin ist, eine neue Klasse mit Ihrer obj -Instanz als Prototyp zu erstellen. Sie können dann den Zugriff auf die alten Funktionen blockieren, indem Sie für ein Objekt der neuen Klasse leere Schlüssel hinzufügen:

%Vor%

(Dies basiert teilweise auf den Power Constructor-Funktionen von Crockford, hier diskutiert .)

BEARBEITEN: Ich habe den obigen Code aktualisiert, um Ihre Kommentare zu adressieren. Es ähnelt nun Ihrer Implementierung, ist aber einfacher und vermeidet das Problem constructor . Wie Sie sehen, beziehen sich Verweise auf öffentliche Funktionen jetzt auf das alte Objekt.

    
nrabinowitz 25.02.2011 05:31
quelle
1

Wenn instanceof funktioniert, müssen wir die Vererbung verwenden, wie die @ nabinowitz-Lösung. In dieser Lösung werden unerwünschte Methoden mit Schlüsseln, die auf null gesetzt sind, verborgen, und diese Schlüssel sind für den Benutzer zugänglich, so dass sie möglicherweise vom Benutzer zurückgesetzt werden. Wir können dies verhindern, indem wir diese Schlüssel in einem Zwischenobjekt verbergen und aus einer Zwischenklasse instanziiert werden, damit die Vererbung nicht bricht.

%Vor%

Im folgenden Beispiel stellen i und j zwei Methoden zum Implementieren von Elementwerten dar. Einer ist das private Mitglied in der Schließung und der andere ist öffentliches Mitglied der Klasse.

%Vor%

Wie Sie sehen, sind alle Setter- und Sink-Methoden im eingeschränkten Objekt verborgen. Der Benutzer kann nur Getter verwenden oder den Wert von i und j erhöhen.

    
Cat Chen 26.02.2011 06:45
quelle
0

Wenn Sie nur bestimmte Methoden in Ihrem Objekt als public verfügbar machen und den Rest als privat betrachten möchten, können Sie so etwas tun (im folgenden Beispiel wird privateMethod2 nie in dem neuen Objekt "read only" angezeigt, das an das Objekt zurückgegeben wird Benutzer):

%Vor%     
Gobhi 20.02.2011 17:13
quelle
0

Was Sie suchen, wird in JavaScript als Modulmuster bezeichnet. Es ist ziemlich nah an dem, was Gobhi beschreibt, aber im Allgemeinen ist es eine selbstausführende Funktion.

Details finden Sie hier:

Ссылка

und:

Ссылка

    
Greg 23.02.2011 17:28
quelle
0

Sie wählen einen sehr komplizierten Ansatz. Geben Sie zuerst weitere Details an:

  • Ist es wirklich wirklich notwendig, den ursprünglichen Objektprototyp zu erweitern (oder wie oft Sie den Objektprototyp zur Laufzeit ändern)?
  • Wie viele verschiedene Objekte werden Sie erstellen? Mit anderen Worten, ich meine: erstellt aus dem gleichen Objekttyp, aber mit verschiedenen öffentlichen Methoden.
  • Wie viele Objekttypen möchten Sie sperren?
  • Wie oft planen Sie, Ihren Code zu aktualisieren?
  • Verwenden Sie irgendeine Art von Minifier / Compiler?

Antwort auf Kommentar 1 :

  • Wenn Sie alle Objekte sperren, ist es eine Frage der Zeit, wann Sie Leistungsprobleme (insbesondere mit IE) behandeln.
  • Bisher haben Sie 2-3 Objekttypen, die Sie sperren möchten. Wäre es nicht einfacher, diese 2-3 Objekte im Delegationsmuster vorzubereiten? Denken Sie daran, dass Sie den Preis für die Flexibilität zahlen müssen;
  • Verwenden Sie im erweiterten Modus den Closure-Compiler . Wenn Sie dieses Werkzeug nutzen, lernen Sie, Objekteigenschaften zu verschleiern und die öffentliche Schnittstelle zu verlassen. Außerdem führt jeder Codewechsel und die Neukompilierung zu neuen versteckten Variablen- / Funktionsnamen, so dass man versucht, zu erraten, ob man die Funktion setA oder getA hat.
  • Und nicht zuletzt. Versuchen Sie, Ihre öffentliche Schnittstelle so sauber und klein wie möglich zu halten. Das bedeutet: Schließen Sie Ihren gesamten Code mit anonymer Funktion ein und geben Sie möglichst wenige Objekte / Methoden / Eigenschaften frei.

Ein bisschen mehr über Closure-Compiler-Verschleierung funktioniert.

  1. Kompilieren benennt alle Objekteigenschaften um in: aa, ab, ac, etc .;
  2. Sie geben öffentliche Methoden / Eigenschaften an: a.prototype.getA = a.prototype.aa; (Intern verwenden Sie die Methode "a.prototype.aa". Dies bedeutet, dass die öffentliche Methode durch einen beliebigen Wert ersetzt werden kann - dies hat keine Auswirkungen auf Ihren Code);
  3. Und schließlich offenbaren Sie das Objekt: window ['foo'] = new a;

Die folgende Methode wird von Google verwendet (GMaps, GMail und usw.).

    
jrumbinas 24.02.2011 06:24
quelle
0

Ich dachte @ nrabinowitz getRestricted ( Link ) Funktion war so ziemlich die Antwort, nach der Sie gesucht haben.

Ich bin kein großer Fan von GOF-Pattern-Anwendungen in JavaScript (es gibt eine ganze Diskussion an sich). Aber das riecht für mich wie ein Dekorateur , da wir das Laufzeitverhalten bei bestimmten Objekten ändern - aber umgekehrt - ein De- Dekorateur wenn Sie mögen:)

    
johnhunter 25.02.2011 07:28
quelle
-1

vielleicht:

%Vor%     
alexl 23.02.2011 10:20
quelle
-1

Ich würde sagen, dass das Muster, das zu Ihrer Situation ziemlich genau passt, der Proxy ist.

UPDATE: Wie die Kommentare zeigen, sollte ein Proxy die gleiche Schnittstelle wie das reale Objekt unterstützen und daher nicht gut zu dem in der Frage angegebenen Problem passen. Am Ende des Wikipedia Artikels auf Proxy habe ich einen Link zu einem interessanten Artikel gefunden, der Proxy, Adapter und Facade vergleicht Muster.

    
Simon Groenewolt 23.02.2011 14:41
quelle