Hoe werkt JavaScript OO

 
14 november 2009

Object georiënteerd programmeren in JavaScript is synthetisch. Het is mogelijk maar ziet er vreemd uit als je het terug leest.
Er zijn verschillende JavaScript bibliotheken die OO programmeren in JavaScript vereenvoudigen maar het blijft niet hetzelfde als bijvoorbeeld Java of C#.
Na een hoop programmeren in JavaScript met Ext wilde ik kijken of ik het zelf kon zonder de toeters en bellen. En beter begrijpen hoe het OO programmeren in JavaScript werkt.

Ik ben wat gaan stoeien met ‘pure’ JavaScript om tot dit voorbeeld te komen. Dit is een zeer dom voorbeeld maar demonstreert (in mijn ogen) hoe het principe werkt:

if (!window.Sogyo) {
    Sogyo = {};
}

if (!Sogyo.Vehicle) {
   Sogyo.Vehicle = {};
}

Sogyo.Vehicle = function () {
}

Sogyo.Vehicle.prototype.move = function () {
   document.write("[Vehicle]");
}

if (!Sogyo.Bike) {
    Sogyo.Bike = {};
}

Sogyo.Bike = function () {
}

Sogyo.Bike.prototype.move = function () {
   Sogyo.Vehicle.prototype.move();	
   return "Ik ben een motor";
}

if (!Sogyo.Car) {
   Sogyo.Car = {};
}

Sogyo.Car = function () {
}

Sogyo.Car.prototype.move = function () {
   Sogyo.Vehicle.prototype.move();	
   return "Ik ben een auto";
}

var bike = new Sogyo.Bike();
document.write(bike.move());

var car = new Sogyo.Car();
document.write(car.move());

Bij het uitvoeren van deze code komt het volgende in beeld (in de browser):

[Vehicle]Ik ben een motor[Vehicle]Ik ben een auto 

De move methode bij de Car en Bike ‘class’ roepen hard de parent move methode aan op Vehicle. Dit is nu een niet al te intelligente methode die iets neerzet op het HTML document.

Het demonstreert wel hoe frameworks als Prototype dit doen.
Bij prototype is er een reeds geinstantieerde functie genaamd Class. Bij het aanroepen van deze functie worden eigenschappen en methoden gekopieerd om het gedrag mee te nemen naar het afgeleid object. De aanroep naar de parent classe die ik in mijn voorbeeld zelf doe wordt automatisch, via event rewiring, gedaan in the Class functie.

Om een class aan te maken in Prototype ziet er als volgt uit:

MyClass = Class.create({
   initialize: function() {
      alert("Hoi");
   }
});

var test = new MyClass();

Dit voorbeeld geeft als resultaat de alert met de tekst ‘Hoi’.

Ik de laatste tijd mogen ontdekken dat JavaScript is een zeer krachtige taal is. Het enige wat ik jammer vind is dat object georiënteerd programmeren in JavaScript synthetisch is en dat vereist (zo goed als) om gebruik te maken van bestaande JavaScript frameworks.
Want ik denk dat meerdere mensen het met mij eens zijn als ik zeg dat het tweede voorbeeld een stuk duidelijk is dan het eerste…


Werken met ?
Kijk dan bij onze mogelijkheden voor starters en/of ervaren IT'ers.


Categorieën: Overige talen en platformen

Tags: , , , , , ,


Reacties (2)

  • Je mist nog een stukje waardoor Bike en Car niet overerven van Vehicle, wat waarschijnlijk wel je bedoeling is.

    Als je de volgende regel toevoegt, dan krijg je als resultaat ‘false’:
    document.write(‘Bike instanceof Vehicle? ‘ + (bike instanceof Sogyo.Vehicle));

    In de definitie van Vehicle (die je overigens netjes in een namespace hebt geplaatst) kun je het volgende toevoegen:
    Sogyo.Bike.prototype = new Sogyo.Vehicle;

    Je hoeft dan geen methods op Bike toe te voegen om expliciet de super method van Vehicle aan te roepen.

    Geplaatst op 29 december 2009 om 12:22 Permalink

  • Tom schreef:

    Ten eerste is het wellicht handig om op te merken dat de ‘Prototype’ library iets anders is als het javascript ‘prototype’ keyword (zelfs op meta-niveau is javascript case-sensitive!). Ik vermoed dat de eerste een bak met code omtrent de laatste encapsuleert.

    Zelf ben ik van mening dat ‘OOig’ javascripten niet (zo goed als) een framework vereist. Ik denk dat de voorbeelden ook niet helemaal een eerlijke vergelijking geven, in het tweede voorbeeld definieer je namelijk alleen een constructor, terwijl het eerste voorbeeld wat lijviger is.

    Als laatste vind ik het jammer dat het Ext-framework (en laat ik gokken ook Prototype) het erg moeilijk maakt om dingen ‘private’ te maken. In feite reflecteert het ’t object wat je aan de Class.Create() functie meegeeft, en gaat al die zaken op je instantie ‘this.’en. Alle properties en functies die je er dus op zet zijn per definitie publiek toegankelijk. In wat jij ‘pure’ javascript noemt is het mogelijk om toch het een en ander te verbergen, door creatief met de constructor functie om te gaan. Een kort voorbeeld:

    TestClass = function() {
    var a = “dit is a”;
    this.b = “dit is b”;
    this.testFunction = function(arg) {
    alert(arg + a + this.b);
    }
    }

    Nadat hier met ‘var testObject = new TestClass()’ een object van gemaakt is, is b aanroepbaar via testObject.b, maar a niet, terwijl de inner functie wel toegang heeft tot a (deze prachtige/hilarische/bloedlinke constructie schijnt overigens een “closure” te heten).

    Geplaatst op 16 november 2009 om 9:38 Permalink