[Sisällys] [Seuraava]

JavaScriptin objektit

JavaScript-kielen objektimalli eroaa ratkaisevasti esimerkiksi C++-kielestä. Tähän on syynsäkin; toisin kuin C++-kielessä JavaScript:issä ei muuttujille määrätä mitään tyyppiä niiden määrittelyvaiheessa.

JavaScript-kielen objektimalli ei perustu luokkiin. Se perustuu pikemminkin prototyyppeihin, mikä tarkoittaa sitä, että uusia objekteja luodaan periaatteessa kloonaamalla ja laajentamalla vanhoja. Kuitenkin objektimalli on hyvin rajoittunut, sillä siitä puuttuvat monet objektiohjelmointikielille tyypilliset ominaisuudet kuten tiedon piilotus ja varsinainen polymorfismi.

Kaikki objektit ovat referenssejä. Tämä tarkoittaa siis sitä, että kun objekti sijoitetaan toiseen muuttujaan sitä ei kopioida, vaan ainostaan sen referenssi (osoitin) kopioituu.


Syntaksi

Metodifunktioita ja jäsenmuuttujia osoitetaan samaan tapaan kuin kuin monissa muissakin kielissä, eli piste-operaattorilla:

objekti.metodi() objekti.ominaisuus = 0 x = objekti.muuttuja

Jäsenmuuttujia voidaan osoittaa myös käyttämällä jäsenen nimeä taulukon indeksinä eli tyyliin:

objekti["ominaisuus"] = 0 // sama kuin: objekti.ominaisuus = 0

Toki on myös mahdollista käyttää objektia normaalin taulukon tapaan eli:

objekti[0] = 0 objekti[1+a] = 1

Objekteista luodaan luodaan instansseja new -operaattorilla samaan tapaan kuin C++-kielessä. Eli operaattorille annetaan argumenttina instantoitavan luokan nimi sekä suluissa muodostimelle (constructor) välitettävät parametrit.

a = new lintu("Varpunen") b = new animal()

Objektit voidaan tuhota delete-operaattorilla.


Jäsenmuuttujien määrittely

Objektin luominen alkaa sillä, että määritellään funktio, jonka nimenä on luotavan olion nimi. Tämä funktio vastaa C++-kielen muodostinta. Tässä funktiossa yksinkertaisesti sijoitetaan jotkin arvot olion sisältämiin jäsenmuuttujiin, jolloin objektille luodaan automaattisesti kyseiset jäsenmuuttujat. Funktio voi ottaa vapaasti valittavan määrän parametreja.

Esimerkkinä luokka auto:

function auto(valmistusvuosi,merkki) { this.valmistusvuosi = valmistusvuosi this.merkki = merkki }

Funktion sisällä käytetään objektia this, jonka arvona on se objektin instanssi, joka jäsenfunktiota kutsui. Eli this-objektin avulla jäsenmuuttujiin voidaan viitata.

Luokasta auto voidaan tehdä instanssi käyttäen new-operaattoria:

oma_auto = new auto(1981,"Lada")

Nyt meillä on käytössä muuttujaan oma_auto talletettu objekti, jonka tyyppinä on auto. Sen jäsenmuuttujien arvoina on 1981 ja "Lada".

Seuraavanlainen ohjelmapätkä asettaisi muuttujien a ja b arvoiksi 1981 ja "Lada":

a = oma_auto.valmistusvuosi b = oma_auto.merkki

Indeksointimahdollisuus voidaan tehdä objektille luomalla sille yksi tai useampia numeerisia jäseniä seuraavasti:

function taulukko(koko) { var i for (i = 0; i < koko; i++) { this[i] = 0 } }

Eli jäsenfunktioden lisäksi muodostimessa voidaan määrittää objektille indeksointimahdollisuus. Itse asiassa riittäisi, että taulukon ensimmäiselle alkiolle sijoitettaisiin jokin arvo, sillä objekteille voidaan luoda milloin tahansa lisää jäseniä.

Milloin tahansa voidaan antaa esimerkiksi käsky:

oma_auto.rengasleveys = 10

jolloin muuttujan oma_auto sisältämälle luokan instanssille syntyy uusi jäsenmuuttuja nimeltä rengasleveys. Tämä jäsenmuuttuja luodaan kuitenkin ainoastaan tälle yhdelle instanssille, eikä saman luokan muut instanssit muutu tästä millään tavalla.


Jäsenfunktioiden eli metodien määrittely

Jäsenfunktioiden määrittely toimii hieman samalla tavalla kuin muodostimenkin määrittely. Metodifunktiot määritellään aluksi ihan tavallisina funktioina, lukuunottamatta oletusta, että this-objekti on olemassa. Tämän jälkeen luokan muodostimessa sijoitetaan tämän funktion nimi haluttuun jäsenmuuttujaan.

Esimerkkinä jo aihemmin käsitelty luokka auto, jolle määritellään metodifunktio vuosia(), joka palauttaa auton iän vuonna 1997:

function vuosia() { return (1997 - this.valmistusvuosi) } function auto(valmistusvuosi,merkki) { this.valmistusvuosi = valmistusvuosi this.merkki = merkki this.vuosia = vuosia }

Kuten esimerkistä nähdään, funktion vuosia nimi sjoitetaan muodostimessa objektin jäsenmuuttujan vuosia arvoksi. Määritellyn funktion ja jäsenmuuttujan nimien ei tarvitse välttämättä olla samoja.

Nyt autosta voidaan luoda instassi ja sille voidaan kutsua jäsenfunktiota:

oma_auto = new auto(1981,"Lada") ika = oma_auto.vanhuus()

Metodifunktio voi ottaa myös parametreja, aivan kuten tavallisetkin funktiot.

Jokaiselle objektille voidaan määritellä erityinen metodi toString() jota kutsutaan kun objektia muutetaan merkkijonoksi.


Perintä ja prototyypit

JavaScript ei perustu luokkiin kuten useat muut oliokielet, vaan prototyyppeihin. Perintä tapahtuukin ottamalla jokin aihemmin määriteltävä olio prototyyppimalliksi ja laajentamalla sitä.

Esimerkkinä luokka Elikko:

function Elikko() { this.ika = 0 }

Nyt halutaankin luoda uusi olio tyyppiä Koira, joka perii kaikki Elikko-olion ominaisuudet. Tämä tapahtuu siten, että konstruktorin määrittelyn jälkeen asetetaan Koira-olion prototype-kentän arvoksi Elikko-objekti:

function Koira(n) { this.ika = n; this.hauku = hauku; } Koira.prototype = new Elikko

Nyt meillä on uusi konstruktori joka kutsuttassa luo instanssin objektista tyyppiä Koira, joka myöskin tyyppiä Elikko.

Filosofia tässä on sellainen, että kun oliossa viitataan johonkin ominaisuuteen, sitä ensin lähdetään etsimään oliosta itsestään. Jos sitä ei löydy, tutkitaan seuraavaksi prototype-kentän osoittama olio. Jos sitä ei vieläkään löydy, jatketaan taas ylöspäin.


this

Avainsanalla this voidaan viitata nykyiseen objektiin. Yleensä tätä käytetään metodifunktioissa, jolloin this viittaa objektin instanssiin joka metodifunktiota kutsui.

Syntaksi

this[.ominaisuus]

Esimerkki

Olkoon määriteltynä objekti auto ja sillä ominaisuus vuosi. Metodifunktio asetaVuosi(), joka ottaa parametrina luvun ja asettaa sen ominaisuuden vuosi arvoksi, voitaisiin määritellä seuraavasti:

function asetaVuosi(n) { this.vuosi = n; }


Simo.Sarkka@iki.fi