JavaScript
Objekter
klasser
JavaScript
Børre Stenseth
OOP >Klasser

Klasser i JavaScript

Hva

Vi så i modulen Objekter på objekter . Nå skal vi se hvordan vi kan introdusere klasser ved hjelp av en konstruktor, som har formen av en funksjon, for så å lage forekomster, objekter, av denne klassen.

Vi begynner med et enkelt eksempel.

Anta:

function person(){
 this.navn='ole';
 this.adresse='halden';
}

Hvis vi nå skriver følgende:

var naboen = new person();

har vi satt opp et nytt objekt, naboen. Merk at vi altså oppretter objektet ved å kalle en funksjon. Funksjonskallet fungerer som konstruktør og det returnerer et objekt. De to egenskapene, navn og adresse, er lokale og vi har brukt this for å angi at de er speielle for det objektet som etableres.

Vi kan nå skrive naboen.navn og få ole

Vi kan videre lage følgende:

function person(nvn,adr){
 this.navn=navn;
 this.adresse=adr;
}

Dersom vi nå oppretter et objekt:

var naboen = new person('Hans','Moss');

og naboen.adresse gir oss Moss.

Vi tar eksempelet et steg videre og legger inn en metode i klassen.

function person(nvn,adr){
 this.navn=nvn;
 this.adresse=adr;
 this.showMe = function(){return this.navn+" fra "+this.adresse}
}

dersom vi nå oppretter et objekt:

var naboen = new person('Jens','Sarp');

og naboen.showMe() gir oss: Jens fra Sarp.

Alternativt

Vi kan skrive følgende direkte:

var minbil = new Object();
minbil.merke = 'toyota';
minbil.farge = 'blå';

Det vil si at vi tilordner nye egenskaper til et nytt generelt objekt. Og vi kan fortsette med å plante en funksjon:

minbil.vis = function(){
	return 'Det er en '+this.farge+' '+this.merke;
}
minbil.vis();

Vil gi resultatet: "Det er en blå toyota"

eller

Vi kan legge til funksjonaliteten som et objekt:

var minbil = new Object();
minbil.merke = 'toyota';
minbil.farge = 'blå';
minbil.visfram = new function()
{
	var vis=function(){
		return 'Det er en '+this.farge+' '+this.merke;
	}
	return vis;
};

Setningen:

minbil.visfram();

Vil gi resultatet: "Det er en blå toyota"

Eksempel 1

Vi gjør et eksperiment med å plante egenskaper og funksjoner i noen bilde-elementer (img). (jada, det kune vært lagt mer arbeid i layout)

bs1 bs2 bs3

og før musa over bildene.

Den sentrale koden i eksempelet er slik:

_tester3.js

Det involverte stilsettet er enkelt:

_tester3.css

Prototype og arv

Alle objekter i Javascript har en egenskap som heter prototype. Vi kan betrakte denne som en generell superklasse. På samme måte som vi plantet egenskaper i objektene våre ovenfor kan vi plane egenskaper i prototype,

Eksempel 1

Vi kan lage følgende enkle konstruksjon:

function land(navn){
 this.land=navn;
}

function sted(hvor){
 this.by=hvor;
}

var byliste=new Array();

sted.prototype=new land('norge');
byliste[0]=new sted('moss');
byliste[1]=new sted('halden');

sted.prototype=new land('sverige');
byliste[2]=new sted('uddevalla');

sted.prototype=new land('danmark');
byliste[3]=new sted('aalborg');

En utskrift av byliste, byliste[ix].by+' i '+byliste[ix].land, vil gi oss

moss i norge
halden i norge
uddevalla i sverige
aalborg i danmark

Greitt nok, men gevisnten er ikke stor. Vi ville oppnådd akkurat det samme med å la landsnavnet være en egenskap ved stedet i en flat klassestruktur.

Eksempel 2

La oss se på hvordan vi kan subklasse et land til republikk eller kongedømme:

function land(nvn){
 this.navn=nvn;
 this.show=function(){return this.navn};
}
function republikk(nvn){
 this.prototype=new land(nvn);
 this.show=function(){
  return this.prototype.show()+ ' som er en republikk'
 };
 }
function kongerike(nvn){
 this.prototype=new land(nvn);
 this.show=function(){
  return this.prototype.show()+ ' som er et kongedømme'
 };
}

var landliste=new Array();

landliste[0]=new kongerike('norge');
landliste[1]=new kongerike('danmark');

landliste[2]=new republikk('frankrike');
landliste[3]=new republikk('italia');

Som gir ( landliste[ix].show() ):

norge som er et kongedømme
danmark som er et kongedømme
frankrike som er en republikk
italia som er en republikk

Vi kunne oppnådd det samme ved å skrive:

function land(nvn){
   this.navn=nvn;
   this.show=function(){return this.navn};
}
function republikk(nvn){
   this.prototype=republikk.prototype;
   this.navn=nvn;
   this.show=function(){
     return prototype.navn+' som er en republikk'
   };
}
 function kongerike(nvn){
   this.prototype=kongerike.prototype;
   this.navn=nvn;
   this.show=function(){
         return prototype.navn+' som er et kongedømme'
   };
 }

 var landliste=new Array();

 kongerike.prototype=new land();
 republikk.prototype=new land();

 landliste[0]=new kongerike('norge');
 landliste[1]=new kongerike('danmark');

 landliste[2]=new republikk('frankrike');
 landliste[3]=new republikk('italia');

Vi ser at dette åpner for at vi dynamisk kan endre hva som er prototype for en klasse, altså hvilken klasse vi ønsker å subklasse.

Eksempel 3

Vi kan ta for oss personer og bileiere. Vi tenker oss altså at bileier skal være en subklasse av person. Vi kan da lage følgende konstruksjon:

function person(nvn,adr){
 this.navn=nvn;
 this.adresse=adr;
 this.show=function(){return this.navn+' fra '+this.adresse}
}
function bileier(mrk,frg,nvn,adr){
 this.merke=mrk;
 this.farge=frg;
 this.prototype=new person(nvn,adr);
 this.show=function(){
  return this.prototype.show()+' kjører en ' 
        +this.farge+' '+this.merke;
 }
}

og vi kan bruke det til å lage en array av personer, der noen er bileiere, slik:

var liste=new Array();
liste[1]=new bileier('toyota','blå','ole','moss');
liste[2]=new bileier('ford','gul','hans','mysen');
liste[3]=new bileier('vw','grønn','gudrun','marker');
liste[3].prototype=new person('kristian','sarpsborg');
liste[4]=new bileier('opel','hvit');
liste[4].prototype=new person('marit','askim');
liste[5]=new person('sverre','rakkestad');

En utskrift av lista, liste[i].show(), vil gi følgende:

ole fra moss kjører en blå toyota
hans fra mysen kjører en gul ford
kristian fra sarpsborg kjører en grønn vw
marit fra askim kjører en hvit opel
sverre fra rakkestad

Merk liste[3], som "bytter eier", altså får ny person. I andre språk ville vi vel kalle dette dynamisk subklassing.

Merk også liste[4], som etableres uten eier. Vi ser litt nærmere på dette. Hvis vi skriver:

p=new bileier('opel','hvit');
alert(p.show());
p.prototype=new person('marit','askim');
alert(p.show());

vil vi i tur og orden få:

 undefined fra undefined kjører en hvit opel
 marit fra askim kjører en hvit opel

Eksempel 4

Endre prototype for en std klasse.

String er en klasse i JavaScript og alle stringer behandles som objekter. Vi kan lage endre prototypen til string ved å innføre nye metoder. Det skal alltid være slik med stringer at vi returnerer et nytt objekt, det vil si at originalen ikke endres. Vi kan for eksempel lage en metode som fjerner alle siffere i en string:

function test(){
String.prototype.removeDigits = function() {
	return this.replace(/[0-9]/g, '')
	}
var S="123take5";
var T=S.removeDigits()
alert(T);
}

OOP >Klasser