You may want to put some text here

Javascript object georiënteerd programmeren

Na het lezen van dit artikel zal er voor vele webdevelopers een nieuwe wereld opengaan. Het is dus zo dat Javascript een zeer krachtige object gebaseerde taal is en niet zomaar een taalje waarmee je afbeelding rollovers kan maken en van die irritante pop-ups.

Belangrijk om weten is dat Javascript geen volledig object georiënteerde taal zoals Java maar een object gebaseerde taal. Waarom zou je dan objecten gaan gebruiken? Het is zo dat het werken met objecten je gaat helpen bij het begrijpen hoe Javascript werkt. Als tweede voordeel zal je je code op een gemakkelijke en snelle manier kunnen uitbreiden en aanpassen.

Primitieve data types

Javascript heeft standaard vijf verschillende types van data aan boord.

  • Undefined
  • Null
  • Boolean
  • Number
  • String

Een Boolean is zoals in elke andere taal true of false.

var BoolValue = true;

Een Number is een reeks van cijfers die een nummer voorstellen.

var NumberValue = 548;

Een String is een reeks van nul of meer characters.

var StringValue = “Dit is een String”;

In Javascript heb je een operator die teruggeeft van welk datatype een variable is.

var  BoolValue = true;
var NumberValue = 548;
var StringValue = “Dit is een String”;
alert(typeof BoolValue);         // Geeft “boolean”
alert(typeof NumberValue);       // Geeft “number”
alert(typeof StringValue);       // Geeft “string”

Objecten

Een object is een verzameling van properties en methodes. Een propertie is simpel gezegd een variable van een object. Een methode is een bewerking binnen een object bijvoorbeeld voor het optellen van twee properties.

Javascript heeft heel wat ingebouwde objecten. Denk maar aan Array, Image, Date en zelfs alle primitieve datatypes zijn objecten. Bekijk even het volgende voorbeeldje waar er een nieuw Image object wordt aangemaakt en vervolgens de src propertie wordt geset.

var VoorbeeldImage = new Image();
VoorbeeldImage.src = “mijnlogo.gif”;

De eerste lijn van het voorbeeld maakt een nieuwe instantie van het Image object. Op de tweede lijn wordt de propertie src van het nieuwe object VoorbeeldImage geset.

Zoals het bovenstaande voorbeeld, kan je instanties maken van alle ingebouwde objecten waarna je properties kan gaan setten met behulp van de punt notatie.

Eigen objecten aanmaken

Allemaal geweldig plezant maar hoe kan je nu zelf objecten maken?

Om gemakkelijk te beginnen zal ik als voorbeeld een klasse maken waar je twee getallen in kan setten en waar je vervolgens de som van kan opvragen.

function Vierkant(breedte, hoogte){
this.breedte = breedte;
this.hoogte = hoogte;
}

Met bovenstaande code heb je een object aangemaakt in Javascript. Veel nut heeft dit object op dit moment nog niet omdat je er alleen nog maar gegevens kan instoppen en terug kan opvragen.

Om het object wat meer functionaliteit te geven ga je een nieuwe methode aanmaken in het object waarmee je de oppervlakte van het vierkant kan opvragen. De manier waarop je methode zal schrijven is de inner function methode, wat niet meer wil zeggen als een functie in een functie.

function Vierkant(breedte, hoogte){

// Oppervlakte opvragen
function getOppervlakte(){
return  breedte * hoogte;
}

//  Constructor
this.breedte = breedte;
this.hoogte = hoogte;
this.getOppervlakte =  getOppervlakte;

}

Zoals je kan zien in de getOppervlakte methode kan je gebruik maken van de lokale variable. Merk ook op hoe ik in de constructor getOppervlakte koppel aan de functie.

this.getOppervlakte = getOppervlakte;

Dit zal ervoor zorgen dat je gebruik kan maken van de punt notatie om de oppervlakte op te vragen. Als voorbeeld maak je een nieuw vierkant aan met breedte en een hoogte van respectievelijk 10 en 20. Vervolgens toon je met een alert de oppervlakte van het vierkant.

var vierkanttje = new Vierkant(10, 20);
alert(vierkanttje.getOppervlakte());      // Resultaat: 200

function Vierkant(breedte, hoogte){

// Oppervlakte opvragen
function getOppervlakte(){
return this.breedte  * this.hoogte;
}

// Constructor
this.breedte = breedte;
this.hoogte = hoogte;
this.getOppervlakte =  getOppervlakte;

}

Een andere manier om methodes toe te voegen aan een object is de volgende:

function Vierkant (breedte, hoogte){

// Constructor
this.breedte = breedte;
this.hoogte = hoogte;

// Oppervlakte opvragen
this.getOppervlakte =  function(){
return  this.breedte * this.hoogte;
}

}

Naar deze manier van werken gaat mijn persoonlijke voorkeur uit omdat je hier geen extra regels meer moet zetten in je constructor voor elke functie die je maakt.

Je kunt ook aan je methodes de mogelijkheid geven om parameters te ontvangen. Als voorbeeld om het gebruik van parameters te tonen heb ik een methode geschreven waaraan je een oppervlakte kan meegeven en die vervolgens teruggeeft hoeveel keer het vierkant in de meegegeven oppervlakte past.

// Hoeveel vierkanten geraken er in de
// opgegeven oppervlakte
this.getPassenIn = function(grote_oppervlakte){

// Haal  oppervlakte van de huidige vierkant op
var oppervlakte =  this.getOppervlakte();

// Kijk  of er een grote oppervlakte is opgegeven
// als paramter, als dit  niet zo is geef dan een
// een foutmelding terug
if(typeof  grote_oppervlakte != 'number'){
return  "De opgegeven paramter is geen getal!";
}

// Geef  terug hoeveel keer de vierkant in de
// grote oppervlakte past
return  Math.floor(grote_oppervlakte/oppervlakte);

}

Deze code plak je bij in je klasse onder de methode getOppervlakte. Het aanroepen van deze methode gaat dan als volgt:

var vierkanttje = new Vierkant (10, 20);
alert(vierkanttje.getPassenIn(1245));

Deze code zal een alertbox geven met als resultaat 6.

Object types

Binnen Javascript zijn er drie verschillende object types: Native objecten, Host objecten en User-defined objecten.

Native objecten zijn objecten die voorzien zijn door Javascript. Voorbeelden van dit type object zijn String, Number, Array, Image, Date, Math, enzoverder.

Host objecten zijn objecten die voorzien worden in Javascript door de browser. Voorbeelden van dit type zijn objecten als window, document, forms, enzoverder.

User-defined objecten zijn objecten die door jouw aangemaakt zijn. Bijvoorbeeld het object uit ons voorbeeld “Vierkant”.

In Javascript is het zo dat elk element dat properties of methodes heeft een object is, uitgezonderd primitieve types. Je kan Javascript constructors juist hetzelfde aanroepen zoals je dat doet bij een User-defined object zoals in ons voorbeeld.

var afbeelding = new Image(150,200);
afbeelding.src = “computerfaq.gif”;

Na het uitvoeren zullen de properties van het native object afbeelding er als volgt uitzien:

Width = 150
height = 200
src = “computerfaq.gif”

Javascript heeft ook een Object constructor. Deze kan je gebruiken om een nieuw Object object te definieëren. Het Object object is het basis object voor alle types van objecten in Javascript. Maak je nu een Native, Host of User-defined object aan, dan zal dit object altijd overgeërfd zijn van het Object object.

var stringvoorbeeld = "Dit is een string";
alert(stringvoorbeeld);                 //  displays "Dit is een string";
alert(typeof stringvoorbeeld);  //  displays "string";

Je kunnen ook een String object aanmaken door de String constructor te gebruiken.

var stringvoorbeeld = new String("Dit is een  string");
alert(stringvoorbeeld);                 //  displays "Dit is een string";
alert(typeof stringvoorbeeld);  //  displays "object";

Bij het eerste voorbeeld maak ik een primitief String type aan. Bij dit type heb je alleen maar de beschikking over de standaard methodes(length, replace, …) en properties van dat type. Als je nu naar het tweede voorbeeld kijkt, daar maak ik een String object aan. Het voordeel van dit is dat je zelf methodes en properties kan toevoegen aan het object.

In onderstaand voorbeeld maak ik een Number object aan waaraan ik een methode toevoeg voor het verdubbelen van de waarde.

var nummervoorbeeld = new Number(2);
nummervoorbeeld.verdubbel = new function("return this*2");
alert(nummervoorbeeld.verdubbel());

Ook in dit geval kun je functies gaan toevoegen waaraan je parameters kan meegeven. Dit doe je als volgt:

var mijnFunctie = new  function("parameter1","parameter2",  "parameter3"," // functie code");

De grote gelijkenis tussen een primitief type en het Object type is dat ze allebei beschikken over een functie constructor().

Het enige wat een primitief type van properties/methodes heeft is een constructor, die op zijn beurt ervoor zal zorgen dat er gebruik kan gemaakt worden van methodes /properties die gedefinieërd zijn in de native Object constructor functie. Hieronder enkele voorbeelden van deze native methodes/properties:

  • length
  • anchor()
  • big()
  • bold()
  • charAt()
  • charCodeAt()
  • concat()
  • indexOf()
  • lastIndexOf()
  • sub()
  • substr()
  • substring()

Argumenten

Elke functie die je beschrijft beschikt over een private variable argument, dat een array is en bevat alle argumenten die megegeven worden aan een functie. Dit kan erg handig zijn als je een functie wilt gaan maken waar je op voorhand niet weet hoeveel argumenten deze heeft.

Als voorbeeld heb ik een functie gemaakt waaraan je getallen kan meegeven als argumenten, waarna de functie de totale som van de argumenten terug geeft.

function  optellen(){
var totaal = 0;
for(i=0 ; i <  arguments.length ; i++){
totaal +=  arguments[i];
}
return totaal;
}

Deze functie kan als volgt opgeroepen worden:

alert(optellen(5,9,8));   // Geeft 22 als resultaat
alert(optellen(10,5,25,50,200));  //  Geeft 290 als resultaat

Prototype

Elke object constructor heeft een speciale propertie “prototype”. Deze propertie geeft je de mogelijkheid een propertie/methode toe te voegen aan alle objecten aangemaakt via die bepaalde object constructor.

Als voorbeeld zal ik het native String object uitbreiden met een methode om een string om te keren.

// Property
String.prototype.omdraaien = function(){
var chars = this.length  -1;
var resultaat =  "";
for(i=chars ; 0 <= i ;  i--){
resultaat  += this[i];
}
return resultaat;
}

var mijnstring = "Dit is een test";
alert(mijnstring.omdraaien());  // Geeft  als resultaat “tset nee si tiD”

Elke string die je aanmaakt na het definiëren van dit prototype zal deze methode aan boord hebben.

Overerving met Prototype

Overerving van classes is gekend in vele verschillende programmeer- en scripttalen zoals Java, C#, PHP, enzoverder. Wat velen niet weten is dat dit ook mogelijk is in Javascript. Ik zal je met een voorbeeldje tonen hoe je dit kan doen.

Stel je hebt een basis-klasse Figuur met enkele properties en een methode om de oppervlakte van een figuur te vergelijken met een opgegeven oppervlakte.

Vervolgens maak je twee nieuwe klasses aan, met als naam respectievelijk Vierkant en Cirkel. De Klasses Vierkant en Cirkel laat je overerven van de klasse Figuur. Bij het maken van een Vierkant of Cirkel object zal je op dit object ook de methodes en properties kunnen oproepen van de klasse Figuur.

// Basis figuur classe
function Figuur(kleur){
this.kleur = kleur;
this.naam =  "anoniem";

// Controle of figuur  oppervlakte is groter dan de opgegeven oppervlakte
this.isOppervlakteGroterDan  = function(vergelijk_oppervlakte){
var  figuur_oppervlakte = this.getOppervlakte();
if(figuur_oppervlakte  > vergelijk_oppervlakte){
return  true;
}else{
return  false;
}
}
}

// Vierkant classe
function Vierkant(kleur){
this.breedte = 20;
this.hoogte = 20;
if(kleur){
this.kleur  = kleur;
}

// Oppervlakte
this.getOppervlakte =  function(){
return  Math.round(this.breedte * this.hoogte);
}
}

// Cirkel classe
function Cirkel(kleur){
this.straal = 5;
if(kleur){
this.kleur  = kleur;
}

// Oppervlakte
this.getOppervlakte =  function(){
return  Math.round(this.straal * this.straal * Math.PI);
}
}

// Vierkant en Cirkel overerven van Figuur met kleur rood
Vierkant.prototype = new Figuur("rood");
Cirkel.prototype = new Figuur("rood");

Om de bovenstaande lap code wat duidelijker te maken kan je de volgende tests en resultaten eens bekijken.

// Test met vierkant object
var figvierkant = new Vierkant();
alert(figvierkant.naam);        //  Resultaat: anoniem
figvierkant.naam = "Vierkant 1";
alert(figvierkant.naam);        // Resultaat: Vierkant 1
alert(figvierkant.getOppervlakte());      // Resultaat: 400
alert(figvierkant.isOppervlakteGroterDan(100));      // Resultaat: true

// Test met cirkel object
var figcirkel = new Cirkel();
alert(figcirkel.naam);        // Resultaat: anoniem
figcirkel.naam = "Cirkel 1";
alert(figcirkel.naam);        // Resultaat: Cirkel 1
alert(figcirkel.getOppervlakte());      //  Resultaat: 79
alert(figcirkel.isOppervlakteGroterDan(100));        // Resultaat: false

De manier van werken is het zelfde als bij het vorige onderdeel “Prototype”, alleen heb je daar een primitief type uitgebreid met een functie terwijl je in dit voorbeeld een object uitbreid met een object.

Tot slot

Na het lezen van de tutorial zou je meer inzicht gekregen moeten hebben in de werking van Javascript. Dankzij deze tutorial zal jouw Javascript code niet langer een hoop procedurele code zijn, maar een mooi OO script dat duidelijk te begrijpen is en gemakkelijk uit te breiden.

The Author of this post is Wim Mostmans

Wim Mostmans heeft een eigen webontwikkeling bedrijf Sitebase waar hij voltijds voor werkt. Hij beheert ook nog enkele websites waaronder deze en een Computerforum. Blijf op de hoogte van waar Wim mee bezig is door hem te volgen op Twitter.

Leave a Comment