2008-10-22 9 views
9

Ich habe versucht zu lernen, wie man vorhandenen Code zu testen - derzeit lesen Working Effectively With Legacy Code. Ich habe versucht, einige der Prinzipien in JavaScript anzuwenden, und jetzt versuche ich, eine Schnittstelle zu extrahieren.Gibt es einen "richtigen" Weg, Vererbung in JavaScript zu machen? Wenn ja, was ist das?

Bei der Suche nach dem Erstellen von Schnittstellen in JavaScript kann ich nicht viel finden - und was ich über die Vererbung finde, scheint ihre verschiedenen Möglichkeiten zu sein. (Einige Leute erstellen ihre eigenen Basisklassen, um hilfreiche Methoden bereitzustellen, um die Vererbung einfacher zu machen, einige verwenden Funktionen, andere verwenden Prototypen).

Was ist der richtige Weg? Haben Sie ein einfaches Beispiel für das Extrahieren einer Schnittstelle in JavaScript?

Antwort

13

Es gibt keine endgültige richtigen Weg, weil so viele Menschen so viele verschiedene Dinge tun .. Es gibt viele nützliche Muster.

Crockford schlägt vor, dass Sie "mit dem Korn gehen", oder schreiben Sie Javascript in einer Weise, die der prototypischen Natur des Javascript entspricht.

Natürlich fährt er fort zu zeigen, dass das ursprüngliche Modell, das Netscape vorgeschlagen hat, tatsächlich gebrochen ist. Er bezeichnet es als "pseudoklassisch" und weist auf die Irreführung und die unnötige Komplexität hin, die mit diesem Modell einhergehen.

Er schrieb die "Objekt" -Funktion als Abhilfe (jetzt bekannt als Object.create()). Es erlaubt einige sehr leistungsfähige prototypische Muster.

Es ist nicht immer einfach, ein sauberes Interface zu entwickeln, wenn Sie mit altem JavaScript arbeiten müssen, insbesondere nicht bei großen Systemen, die normalerweise mehrere Bibliotheken enthalten und jeweils einen einzigartigen Stil und ein anderes Vererbungsmuster implementieren. Im Allgemeinen würde ich sagen, dass der "richtige Weg" zur Vererbung derjenige ist, der Ihnen erlaubt, eine saubere Schnittstelle zu schreiben, die sich gut im Kontext Ihres Legacy-Codes verhält, aber auch alte Abhängigkeiten im Laufe der Zeit umgestalten und eliminieren kann .

Unter Berücksichtigung der Unterschiede zwischen den Hauptbibliotheksmustern habe ich festgestellt, dass der erfolgreichste Weg in meiner eigenen Arbeit darin besteht, meine Schnittstellen unabhängig von den Bibliotheksschnittstellen zu halten. Ich werde eine Bibliothek oder ein Modul verwenden, wenn es hilfreich ist, aber nicht daran gebunden sein. Dies hat es mir ermöglicht, eine Menge Code umzuformen, einige Bibliotheken auslaufen zu lassen und Bibliotheken als Gerüst zu verwenden, das später optimiert werden kann.

Entlang dieser Linien habe ich Schnittstellen geschrieben, die von Crockfords parasitärem Vererbungsmuster inspiriert wurden. Es ist wirklich ein Gewinn für die Einfachheit. Auf der anderen Seite der Medaille, ich bin mir sicher, dass Sie dafür einstehen könnten, eine Bibliothek auszuwählen, sie in Ihrem Team durchzusetzen und sowohl ihren Vererbungsmustern als auch ihren Schnittstellenkonventionen zu entsprechen.

+2

Wie über einige Links? – pc1oad1etter

3

Schauen Sie sich auch Dean Edwards Base.js an. Sie können einen Blick darauf werfen here, der Blog-Post ist selbsterklärend.

5

Sie betrachten zwei verschiedene Dinge.

Zuerst haben Sie Schnittstellen. Der am meisten akzeptierte Weg, dies zu erreichen, ist Duck Typing ("wenn es wie eine Ente aussieht und wie eine Ente quakt, dann ist es eine Ente"). Das bedeutet, wenn ein Objekt eine Reihe von Methoden der Schnittstelle implementiert, dann ist es diese Schnittstelle. Sie implementieren dies, indem Sie ein Array von Methodennamen verwenden, die eine Schnittstelle definieren. Um zu überprüfen, ob ein Objekt diese Schnittstelle implementiert, sehen Sie, ob es diese Methoden implementiert.Hier ist ein Codebeispiel I bis gepeitscht:

function Implements(obj, inter) 
{ 
    var len = inter.length, i = 0; 
    for (; i < len; ++i) 
    { 
     if (!obj[inter[i]]) 
      return false; 
    } 
    return true; 
} 

var IUser = ["LoadUser", "SaveUser"]; 

var user = { 
     LoadUser : function() 
     { 
      alert("Load"); 
     }, 

     SaveUser : function() 
     { 
      alert("Save"); 
     } 
    }; 

var notUser = { 
     LoadUser : function() 
     { 
      alert("Load"); 
     } 
    }; 

alert(Implements(user, IUser)); 
alert(Implements(notUser, IUser)); 

Jetzt Sie die Vererbung haben. JS hat keine eingebaute Vererbung; also müssen Sie es manuell implementieren. Dies ist nur eine Frage des "Kopierens" der Eigenschaften eines Objekts in ein anderes. Hier ist ein weiteres Codebeispiel (nicht perfekt, aber es zeigt den Punkt):

function InheritObject(base, obj) 
{ 
    for (name in base) 
    { 
     if (!obj[name]) 
      obj[name] = base[name]; 
    } 
} 

var Base = { 
     BaseFunc : function() { alert("BaseFunc from base"); }, 
     InheritFunc : function() { alert("InheritFunc from base"); } 
    } 

var Inherit = { 
     InheritFunc : function() { alert("InheritFunc from inherit"); }, 
     AnotherFunc : function() { alert("AnotherFunc from inherit"); } 
    } 

InheritObject(Base, Inherit); 

Inherit.InheritFunc(); 
Inherit.BaseFunc(); 
Inherit.AnotherFunc(); 

Base.BaseFunc(); 
Base.InheritFunc(); 

Sie wahrscheinlich bei http://www.mootools.net suchen. Es hat meine Lieblingsimplementierung von Klassen. Sie wollen auch auf jeden Fall

http://www.amazon.com/JavaScript-Design-Patterns-Recipes-Problem-Solution/dp/159059908X

Dieses Buch geht in gutes Detail "Pro Javascript Design Patterns", um zu überprüfen, wie OOP in Javascript zu emulieren.

+0

+1 Einfache und klare Erklärung! –

6

Es gibt keine Klasse in Javascript, nur Objekte.
Aber wenn Sie auf Emulation der Klasse basiert objektorientiertes Modell bestehen können Sie verwenden:

 
function ChildClass() { 
    ParentClass.call(this); 
    // Write the rest of your constructor function after this point. 
}; 
ChildClass.prototype = jQuery.extend({}, ParentClass.prototype, ChildClass.prototype); 

jQuery.extend ist eine ‚flache Kopie‘ Funktion aus der jQuery-Bibliothek. Sie können es durch eine andere Objektkopier-/Klonfunktion ersetzen.

+1

der erste Satz kann nicht mehr betont werden – Claudiu

0

Prototyp bietet seine eigenen Gedanken über Vererbung von http://www.prototypejs.org/api/class/create:

var Animal = Class.create({ 
    initialize: function(name, sound) { 
    this.name = name; 
    this.sound = sound; 
    }, 

    speak: function() { 
    alert(this.name + " says: " + this.sound + "!"); 
    } 
}); 

// subclassing Animal 
var Snake = Class.create(Animal, { 
    initialize: function($super, name) { 
    $super(name, 'hissssssssss'); 
    } 
}); 
Verwandte Themen