Objektorientierte Programmierung in JavaScript

von Patrick Freitag | 3 | 2 Kommentare | 21363 Aufrufe

Anzeige Hier werben

Viele halten JavaScript noch immer für den Grundsatz alles Bösen das in den letzten Jahren an Geblinke, Geblitze und anderen Gräueltaten die im Internet kursierten. Seit dem Web 2.0 konnte JavaScript einiges an Punkten gut machen und findet sich mittlerweile sogar in den Top 10 der beliebtesten Programmiersprachen. Die Anwendungsgebiete fallen hauptsächlich in die DOM-Manipulation, Effekte im Browser oder ähnliches. Ebenso hat JavaScript den schlechten Ruf unsicher zu sein, welcher jedoch durch das Sandboxing um einiges verringert wird (ActiveX-Elemente ausgenommen) und durch gute Programmierung vernichtet wird.

JavaScript ist eine auf Objekten basierende Programmiersprache. Es gibt zahlreiche vordefinierte Objekte wie z.B das String oder Window-Objekt.

Klassen und Konstruktor definieren

In JavaScript gibt es keine Klassen-Definition im herkömmlichen Sinne. Klassen werden erst einmal als einfache Funktionen erstellt.

Als Test-Klasse werden wir ein Auto verwenden und daran rumspielen.

Klasse definieren  
HTML
1
2
3
function Car(CarColor) {                
    this.CarColor = CarColor;                
}

Das ist also unsere Klassen-Definition. Wie man sehen kann gibt es in JavaScript kein explizites Schlüsselwort für eine Klasse. JavaScript unterscheidet nur anhand der Initialisierung der Funktion ob es eine Klasse ist oder nicht.

Eine Klasse wird, wie in allen gängigen Programmiersprachen, mit dem Schlüsselwort new initialisiert.

Klasse initialisieren  
HTML
1
2
3
4
5
function Car(CarColor) {
   this.CarColor = CarColor;
}
var Jeep = new Car('blue'); // Initialisierung des Objekts "Car"
alert(Jeep.CarColor); // Direkter Zugriff auf die Eigenschaft "CarColor"

Hier erstellen wir mittels new ein neues Objekt und übergeben dem Konstruktor den Parameter CarColor. Ganz recht, die Funktion ist eigentlich unser Konstruktor. Anschließend wird die öffentliche Eigenschaft CarColor mit dem übergebenen Parameter definiert und mittels alert wird die Eigenschaft CarColor am Bildschirm ausgegeben.

Datenkapselung von Methoden und Eigenschaften

Die Datenkapselung ist in der objektorientierten Programmierung natürlich ein wichtiges und unabdingbares Feature das natürlich auch in JavaScript nicht fehlen darf. In JavaScript existieren nur öffentliche (public) und private (private) Eigenschaften und sogenannte "privilegierte öffentliche Methoden", "nicht-privilegierte öffentliche Methoden" und natürlich private Methoden.

 
JavaScript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
function Car(CarColor) {    

    // öffentliche (public) Eigenschaft
    this.CarColor = CarColor;    

    // privilegierte öffentliche Methode
    this.setCarColor = function(newCarColor) {        
        this.CarColor = newCarColor;        
    }    
}

var Jeep = new Car('blue');            
alert(Jeep.CarColor);
Jeep.setCarColor('orange');            
alert(Jeep.CarColor);

Hier definieren wir die "privilegierte öffentliche Methode" setCarColor mit einem Parameter. Beim Aufruf wird die "öffentliche Eigenschaft" CarColor überschrieben und anschließend wieder ausgegeben.

 
JavaScript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
function Car() {
    
    // private Eigenschaft
    var CarTank = '100 Liter';
    
    // privilegierte öffentliche Methode
    this.setCarTank = function(newCarTank) {
        
        CarTank = newCarTank; // Zuweisung des neuen Tankinhaltes        
        getCarTank(); // Aufruf der privaten Methode
        
    }    
    
    var getCarTank = function() {
        
        // Ausgabe der privaten Eigenschaft
        alert(CarTank);
        
    }
    
}

var Cabrio = new Car();            
Cabrio.setCarTank('200 Liter');
alert(Cabrio.CarTank); // Liefert "undefined"
Cabrio.getCarTank(); // Liefert "is not a function"

Dieses Beispiel veranschaulicht die Zugriffsrechte der einzelnen Methoden und Eigenschaften. Die Eigenschaft CarTank ist privat und kann von außen nicht aufgerufen oder befüllt werden nur innerhalb der Klasse ist das hantieren mit der Eigenschaft möglich. Selbiges für die Methode getCarTank.

In JavaScript ist es möglich bestehende Methoden bzw. Objekte nachträglich zu beeinflussen. Dies funktioniert mittels sogenannten "Prototypen" auf die JavaScript basiert. Dies hat den Vorteil von mehr Unabhängigkeit und Flexibilität für den Programmierer.

 
JavaScript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
function Car() {

    // öffentliche Eigenschaft
    this.CarName = "Audi";
    // private Eigenschaft
    var CarColor = "Black";
    
    // private Methode
    var setCarColor = function(newCarColor) {
        
        CarColor = newCarColor;
        
    }
    
    // privilegierte öffentliche Methode
    this.getCarInfosInside = function() {
        
        setCarColor('Green');        
        alert("CarName:" + this.CarName + " CarColor:" + CarColor);
        
    }
    
}
 
// nicht-privilegierte öffentliche Methode
Car.prototype.getCarInfosOutside = function() {
    
    setCarColor('Green');
    alert("CarName:" + this.CarName + " CarColor:" + CarColor);
    
}

var Audi = new Car();
Audi.getCarInfosInside(); // Liefert "Audi" und "Green"
Audi.getCarInfosOutside(); // Liefert "setCarColor" is not defined, "Audi" und "undefined"

Wie man hier gut sehen kann wird einmal die "privilegierte öffentliche Methode" getCarInfosInside aufgerufen (bitte entschuldigt meine Kreativen Methoden-Namen) und einmal die "nicht-privilegierte öffentliche Methode" getCarInfosOutside. Die Methode in der Klasse hat natürlich vollen Zugriff auf alles was drinnen so abläuft, d.h ich kann auf alle Eigenschaften und Methoden zugreifen. Die Methode außerhalb der Klasse kann lediglich auf öffentliche Eigenschaften und Methoden zugreifen.

Vererbung

Durch die Prototypen-Funktionen ist es möglich Vererbung in JavaScript zu benutzen.

 
JavaScript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// Superklasse
function Car(CarName) {
        
    this.CarName = CarName;
    this.CarWheels = "4";
    
}

// Subklasse
function Audi(CarName) {
    
    // Dieser Konstruktor ruft den Konstruktor der Superklasse auf
    this.constructor(CarName);
    this.CarColor = 'Black';
    
    this.getCarInfos = function() {
        
        alert(this.CarName + " is " + this.CarColor + " and has " + this.CarWheels + " Wheels!");        
        
    }
    
}

Audi.prototype = new Car(); // Hier passiert die Vererbung

AudiA3 = new Audi('Audi A3');
Audi80 = new Audi('Audi 80');

AudiA3.getCarInfos(); // Liefert "Audi A3 is Black and has 4 Wheels"

Audi.prototype.setCarColor = function(newCarColor) {
    
    this.CarColor = newCarColor;
    this.getCarInfos();
    
}

Audi80.setCarColor('Yellow'); // Liefert "Audi 80 is Yellow and has 4 Wheels"

In diesem Beispiel haben wir eine Superklasse Car und die Subklasse Audi. Car besitzt 2 öffentliche Eigenschaften. Eine wird per Parameter befüllt, die andere ist es bereits. Audi besitzt eine 2 privilegierte öffentliche Methoden, dass sind this.constructor und this.getCarInfos. Wobei der Konstruktor nur dafür da ist um die Superklasse aufzurufen ohne sie extra nochmal initialisieren zu müssen. Anschließend passiert die Vererbung mittels dem Prototypen. Dann definieren wir 2 verschiedene Audi's und lassen uns per getCarInfos die Audi A3-Daten ausgeben. Da wir alle Eigenschaften von der Superklasse geerbt haben können wir auf den Namen und die Anzahl der Reifen zusätzlich zugreifen.

Über den Autor: Patrick Freitag
Patrick Freitag arbeitet als Java-Programmierer und Webworker in einer österreichischen Firma und beschäftigt sich seit ca. 6 Jahren mit der Webentwicklung. Neben der Programmierung in JavaScript, Python und PHP sind auch das Markup und Software Architektur seine Leidenschaft. Er ist auch auf Twitter aktiv.
Profilseite betrachten

Kommentare: Objektorientierte Programmierung in JavaScript

Neuen Kommentar schreiben
Klassen in Frameworks
Beantworten

Vielleicht sollte man em Ende des Artikels noch auf Klassen in verschiedenen Frameworks hinweisen/linken. Die sind ja oft sehr gute verbesserungen/erweiterungen von Klassen.

Sonst eine schöne Einführung. Am Amfang von "Klassen und Konstruktor definieren" würde ich initialisierung und definition etwas trennen und der erste satz ist nicht so verständlich. Wenn du erlaubst ändere ich da schnell nen detail :)

Thomas H am 01.09.2008 um 15:11
Re: Klassen in Frameworks
Beantworten

Kannst du gerne ändern. :) Ich hab es nur als "Artikel von mir" reingestellt, da ich es auch auf meinem Blog usw. veröffentlicht hatte. Bin aber immer für Änderungen offen.

Patrick Freitag am 02.09.2008 um 00:43