4 Stimmen

Javascript OOP - Bewährte Praktiken bei der Validierung von Objekten über Schnittstellen oder Prototypen

Ich lerne mehr fortgeschrittene OO-Taktiken für Javascript aus einem C#-Hintergrund kommen und wundere mich über, wie oder wenn seine sogar eine gute Idee, Prototyp-basierte Validierung zu implementieren. Zum Beispiel, wenn ein Objekt oder eine Funktion erfordert einer seiner Parameter eine bestimmte Schnittstelle zu erfüllen, könnten Sie seine Schnittstelle wie so überprüfen,

var Interface = function Interface(i) {
   var satisfied = function (t, i) {
      for (var key in i) {
         if (typeof t !== 'object') {
            return false;
         }
         if (!(key in t && typeof t[key] == i[key])) {
            return false;
         }
      }
      return true;
  }
  this.satisfiedBy = function (t) { return satisfied(t, i); }
}

// the interface
var interfacePoint2D = new Interface({
    x: 'number',
    y: 'number'
}); 

// see if it satisfies
var satisfied = interfacePoint2D.satisfiedBy(someObject); 

Ich habe mir diese Strategie ausgedacht, um ein Objekt nur anhand seiner Schnittstelle zu überprüfen und die interne Implementierung des Objekts zu ignorieren.

Oder sagen Sie, Sie verwenden Prototyp-basierte Vererbung, sollten Sie oder sollte nicht validieren Parameter auf der Grundlage ihrer Prototyp-Funktionen? Soweit ich weiß, verwenden Sie einen Prototyp, um Standardfunktionen zu implementieren, während eine Schnittstelle keine Standardfunktionen vorgibt. Manchmal kann das Objekt, das Sie an eine Funktion übergeben brauchen bestimmte Standardfunktionen, damit diese Funktion funktioniert. Ist es besser, nur gegen eine Schnittstelle zu validieren, oder sollten Sie jemals gegen einen Prototyp validieren, und wenn ja, was der beste Weg, es zu tun?

EDIT -- Ich gebe etwas mehr Hintergrundinformationen, warum ich diese Frage stelle,

Zum Beispiel bei der Entwicklung von Online-Spielen (meist in Javascript geschriebene Spiele). Es gibt 2 Hauptgründe, warum ich in diesem Zusammenhang an Validierung interessiert bin,

1) Bereitstellung einer starken öffentlichen API für die Modifizierung des Spiels, falls gewünscht

2) Verhinderung (oder zumindest starke Entmutigung) von potenziellen Betrügern

Dies erfordert ein Gleichgewicht zwischen Anpassungsfähigkeit und Missbrauch. Eine besondere Situation wäre die Entwicklung einer Physik-Engine, in der Objekte im Spiel auf die Schwerkraft reagieren. In einem realistischen System sollten die Benutzer nicht in der Lage sein, dem System Objekte hinzuzufügen, die nicht auf die Schwerkraft reagieren. Das System verfügt über eine Funktion, die die globale Wirkung der Schwerkraft an jedem beliebigen Punkt ausdrückt:

function getGravityAt(x, y) {
      // return acceleration due to gravity at this point
}

Und Objekte, die reagieren, haben eine Methode, die dies zur Aktualisierung ihrer Beschleunigung nutzt:

function update() {
      this.acceleration = getGravity(this.position); 
}

Das Mindeste, was man tun kann, ist sicherzustellen, dass jedes dem System hinzugefügte Objekt eine "Update"-Methode hat, aber man stellt immer noch nicht sicher, dass die update()-Methode wirklich auf die Schwerkraft reagieren soll. Wenn nur Objekte erlaubt sind, die von einer prototypischen update()-Methode erben, dann weiß man zumindest zu einem gewissen Grad, dass alles im System realistisch reagiert.

2voto

nrabinowitz Punkte 54138

Das ist eine ziemlich subjektive Frage. Ich werde auf die Frage, ob es eine gute Idee, Interface-basierte Validierung in Javascript überhaupt zu tun (es kann gut sein, gute Use-Cases für sie, aber es ist nicht ein Standard-Ansatz in der Sprache) passieren. Aber ich werde sagen, dass es wahrscheinlich ist no eine gute Idee, Objekte auf der Grundlage ihrer Prototypen zu validieren.

Wenn Sie überhaupt nach Schnittstellen validieren, arbeiten Sie wahrscheinlich mit Objekten, die von anderen Programmierern erstellt wurden. Es gibt viele Möglichkeiten, Objekte zu erstellen - einige stützen sich auf Prototypen, andere nicht, und obwohl sie alle ihre Befürworter haben, sind sie alle gültig und wahrscheinlich. Zum Beispiel:

var Point = function(x,y) {
    return {
        x: function() { return x },
        y: function() { return y }
    };
};

var p = new Point(1,1);

Das Objekt p entspricht einer ähnlichen Schnittstelle wie die oben beschriebene, mit der Ausnahme, dass x y y sind Funktionen. Aber es gibt keine Möglichkeit, das zu überprüfen p erfüllt diese Schnittstelle, indem es seinen Konstruktor inspiziert (dieser ist Object() ) oder Point.prototype . Alles, was Sie tun können, ist zu testen, dass p hat Attribute namens x y y und dass sie vom Typ "function" - was Sie oben tun.

Sie könnten möglicherweise darauf bestehen, dass p hat einen bestimmten Vorfahren in seiner Prototypenkette, z. B. AbstractPoint die auch die x y y Funktionen - Sie können verwenden instanceof um dies zu überprüfen. Aber Sie können nicht sicher sein, dass x y y nicht neu definiert worden sind in p :

var AbstractPoint = function() {};
AbstractPoint.prototype.x = function() {};
AbstractPoint.prototype.y = function() {};

var Point = function(x,y) {
    var p = new AbstractPoint(x,y);
    p.x = "foo";
    return p;
}

var p = new Point(1,1);
p instanceof AbstractPoint; // true
p.x; // "foo"

Und, was vielleicht noch wichtiger ist, das macht es schwieriger, benutzerdefinierte Objekte einzufügen, die ebenfalls die Schnittstelle erfüllen, aber nicht von Ihren Klassen erben.

Ich denke also, dass das, was Sie derzeit tun, wahrscheinlich das Beste ist, was Sie sich erhoffen können. Meiner Erfahrung nach sind Javascript-Programmierer viel eher zu verwenden on-the-fly duck-typing als zu versuchen, die Fähigkeiten der statisch typisierten Sprachen zu imitieren:

function doSomethingWithUntrustedPoint(point) {
    if (!(point.x && point.y)) return false; // evasive action!
    // etc.
}

0voto

hurrymaplelad Punkte 25235

Ich werde wiederholen, Typüberprüfung ist nicht idiomatisch Javascript.

Wenn Sie dennoch eine Typenprüfung wünschen, können Sie Googles Verschlusscompiler ist die Implementierung, die ich empfehle. Die Typüberprüfung wird statisch durchgeführt :) Es hat Konventionen für Schnittstellen sowie (Proto-)Typenprüfung.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X