Klasser i JavaScript
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)
og før musa over bildene.
Den sentrale koden i eksempelet er slik:
Det involverte stilsettet er enkelt:
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); }