Javascript

Page 1

JAVASCRIPT Andris Reinman © Tallinn 2009-2010


JavaScript, Andris Reinman

1. Sisukord JAVASCRIPT....................................................................................................................................... 1 1.Sisukord........................................................................................................................................ 2 2.JavaScript......................................................................................................................................4 2.1.Sissejuhatus...................................................................................................................... 4 2.2.Süntaks............................................................................................................................. 5 2.3.Tõstutundlik......................................................................................................................5 2.4.Dünaamiline tüüpimine.................................................................................................... 5 2.5.Parditüüpimine................................................................................................................. 5 3.Andmetüübid................................................................................................................................ 7 3.1.Numbrid............................................................................................................................7 3.2.Stringid............................................................................................................................. 7 3.3.undefined.......................................................................................................................... 7 3.4.null....................................................................................................................................7 3.5.Loogilised väärtused.........................................................................................................7 3.6.Objekt............................................................................................................................... 8 3.7.Väärtuste teisendamine operatsioonides.......................................................................... 8 3.8.Väärtuste edastamine........................................................................................................8 3.9.Prahikoristaja....................................................................................................................9 4.Operaatorid................................................................................................................................. 10 4.1.Aritmeetika..................................................................................................................... 10 4.2.Omistamine.................................................................................................................... 12 4.3.Võrdlemine..................................................................................................................... 13 4.4.Loogilised operaatorid....................................................................................................14 4.5.Bitioperatsioonid............................................................................................................ 16 4.6.Tekst............................................................................................................................... 17 4.7.Objektide elemendid.......................................................................................................17 4.8.Spetsiaalsed operaatorid................................................................................................. 18 4.9.Operatsioonide järjekord................................................................................................ 20 5.Keele struktuurid.........................................................................................................................22 5.1.Tsüklid............................................................................................................................ 22 5.2.Tingimuslaused...............................................................................................................24 5.3.Veatöötlus....................................................................................................................... 25 5.4.Muud lausestruktuurid....................................................................................................26 6.Funktsioonid............................................................................................................................... 30 6.1.Deklareerimine............................................................................................................... 30 6.2.Funktsiooni käivitamine................................................................................................. 31 6.3.Sisendparameetrid.......................................................................................................... 31 6.4.Tagastus.......................................................................................................................... 32 6.5.Skoop..............................................................................................................................32 6.6.Lokaalne skoop...............................................................................................................33 6.7.Sulundid..........................................................................................................................34 6.8.Rekursioonid.................................................................................................................. 35 6.9.Funktsioonide atribuudid................................................................................................36 7.Globaalsed objektid.................................................................................................................... 38 7.1.Globaalsed väärtused......................................................................................................38 2 / 109


JavaScript, Andris Reinman

7.2.Globaalsed funktsioonid.................................................................................................39 7.3.Globaalsed objektid........................................................................................................ 41 8.Objektid ja objektorienteeritud programmeerimine................................................................... 46 8.1.Omadused ja meetodid................................................................................................... 46 8.2.Objekti loomine.............................................................................................................. 47 8.3.Objektide kettimine........................................................................................................ 49 8.4.this.................................................................................................................................. 49 8.5.Konstruktorfunktsioonid................................................................................................ 50 8.6.Prototüübid ja delegeerimine..........................................................................................52 8.7.Avalikud ja privaatsed omadused ning meetodid...........................................................55 8.8.Objektide meetodid........................................................................................................ 56 9.Numbrid...................................................................................................................................... 58 9.1.Numbrite esitamine........................................................................................................ 58 9.2.Omadused....................................................................................................................... 59 9.3.Meetodid.........................................................................................................................60 10.Stringid......................................................................................................................................62 10.1.Stringi loomine............................................................................................................. 62 10.2.UTF-8........................................................................................................................... 63 10.3.Stringi meetodid........................................................................................................... 64 10.4.Mittestandardsed meetodid...........................................................................................69 11.Massiivid...................................................................................................................................71 11.1.Massiivi loomine.......................................................................................................... 71 11.2.Mitmemõõtmelised massiivid...................................................................................... 72 11.3.Massiivilaadse objekti teisendamine............................................................................ 73 11.4.Massiivi elementide kustutamine................................................................................. 73 11.5.length............................................................................................................................ 73 11.6.Massiivide meetodid.....................................................................................................74 12.Aeg............................................................................................................................................78 12.1.Ajatempel..................................................................................................................... 78 12.2.Date.............................................................................................................................. 78 12.3.Meetodid.......................................................................................................................79 13.Matemaatika..............................................................................................................................87 13.1.Konstandid....................................................................................................................87 13.2.Meetodid.......................................................................................................................88 14.Nimeruumid.............................................................................................................................. 94 15.Bitioperatsioonid.......................................................................................................................96 15.1.32 bitised numbrid........................................................................................................96 15.2.Võrdlusoperatsioonid................................................................................................... 97 15.3.Bittide nihked............................................................................................................... 98 15.4.Lippude haldamine....................................................................................................... 99 16.Regulaaravaldised................................................................................................................... 102 16.1.RegExp objekt............................................................................................................ 102 16.2.Regulaaravaldise lipud............................................................................................... 102 16.3.Erimärgid regulaaravaldises....................................................................................... 103 17.Erindid.................................................................................................................................... 105 17.1.throw...........................................................................................................................105 17.2.Error............................................................................................................................105 17.3.try/catch/finally.......................................................................................................... 106 17.4.onError sündmus........................................................................................................ 106 3 / 109


JavaScript, Andris Reinman

4 / 109


JavaScript, Andris Reinman

2. JavaScript 2.1. Sissejuhatus JavaScript on skriptimiskeel, mille lõi Netscape brauseri juures töötanud Brendan Eich. Esialgne tööpealkiri oli Mocha, seejärel LiveScript ning lõpuks sai keel endale nime JavaScript. Algselt oli JavaScript mõeldud ainult brauserisiseseks skriptimiseks, kuid praeguseks on see levinud ka muudele platvormidele. Microsofti brauserites on kunagiste litsentsiprobleemide tõttu (JavaScript on kompanii Sun Microsystems kaubamärk) JavaScripti asemel kasutuses identne keel nimega JScript. JavaScript muutus suhteliselt kiirelt, umbes kaks aastat peale esmast väljatulekut, aastal 1997 ECMAScript nime all standardiks. Seega JavaScript, kuigi ECMAScripti eelkäija, on ametlikult võttes lihtsalt üks ECMAScripti dialekt. Kuna keel arendati ideest standardini üsna kiiresti, on tegu „varajase täiskasvanuga“ sisaldades paljude väga heade võimaluste kõrval ka mitmeid möödalaskmisi (näiteks viite this sidumine funktsioonides globaalse objektiga). Tegu on ülimalt populaarse programmeerimiskeelega, mille edu üheks põhjuseks on olnud keele näiline lihtsus. JavaScripti suudavad osaliseltki kasutada oma veebilehtede elavdamiseks ka inimesed, kes programmeerimisest üldse mitte midagi ei tea. Paraku aga on see keele mainele „päris programmeerijate“ hulgas mõjunud suhteliselt devalveerivalt - arvatakse, et JavaScript muuks ei kõlbagi, kui vaid veebivormide sisu kontrollimiseks ja brauseri aknas liikuvale hiire kursorile animeeritud „saba“ ja ekraanil langevate „lumehelveste“ tekitamiseks. Tegelikkus on siiski midagi muud. Tegu on täisfunktsionaale keelega, millega annab realiseerida vägagi keerulisi aplikatsioone. Heaks näiteks oleks siinkohal Google Docs laadsed teenused, mis pakuvad reaalset alternatiivi töölaua kontoritarkvarale (olles mõnes mõttes isegi paremad, kuna pole tarvis muretseda dokumentidest varukoopiate tegemise üle, kuna faile salvestatakse internetis). JavaScript keelena on suhteliselt omapärane. Puuduvad näiteks standardsed vahendid sisendiks ja väljundiks. Tegu on ka praktiliselt ainsa laiemat tuntust kogunud prototüübipõhise objektorienteeritud keelega. Ning JavaScripti potentsiaal juba leviku poolest on meeletu praktiliselt kõikides maailma arvutites mis on ühendatud internetti, sisaldub JavaScripti interpretaator (selleks on veebibrauser). Keel on sõltumatu nii arvuti operatsioonisüsteemist, kui tegelikult ka tänu piisavale standardiseerimisele ja headele abistavatele teekidele (näiteks Prototype või jQuery) kasutatavast brauserist. JavaScripti on võimalik brauseris väja lülitada, samuti võivad veel levida mõned vanemad brauserid, mis ei toeta hetkel aktuaalset JavaScripti versiooni 1.5 ja mis teevad sellega kõikide kasutajate toetamise keerulisemaks. Eestis on sellest küljest olukord üsna hea ning seda suuresti tänu internetipankadele populaarsusele. Internetipankade lehed nimelt sisaldavad ohtralt JavaScripti, sundides sellega kõiki kliente kasutama JavaScripti toega brausereid. Reeglina pole internetipangas näiteks sisseloginud kasutaja vaates ühtegi „ehtsat“ linki, kogu navigeerimine toimub läbi javascripti funktsioonide. Tõenäoliselt on see mõeldud vältimaks ühe sessiooni ajal mitme brauseriakna avamist. Positiivse kõrvalefektina aga muudab suure kasutajaskonnaga netipankade JavaScripti nõudev lähenemine kõikide JavaScripti arendajate töö kordades kergemaks. Ühilduvuse tagamiseks erinevate brauserite vahel, on raamatus käsitletud JavaScripti versiooni 1.5 ning sellest peamiselt osa, mis on ühilduv JScript versiooniga 5.6.

5 / 109


JavaScript, Andris Reinman

2.2. Süntaks JavaScripti süntaks sarnaneb C ja teiste sarnaste keelte (Java, PHP jne) süntaksile, välja arvatud skoobid, mis JavaScriptis on funktsioonipõhised. Paraku aga sellega sarnasused näiteks Javaga (hoolimata JavaScripti nimest) ka piirduvad. JavaScript on dünaamiliselt ja nõrgalt tüübitud, prototüübipõhine skriptimiskeel, mis on esialgselt mõeldud jooksma „peremeesobjekti“ sees. Sõna „Java“ JavaScripti nimes on vaid omaaegne marketingitrikk, mille tulemuseks on hulk segadust. JavaScript ei ole Java ning JavaScript ei ole Javaga mitte kuidagi seotud (kui mitte arvestada Java jaoks loodud JavaScripti interpretaatorit nimega Rhino). Üheks suureks erinevuseks näiteks keelega C on semikoolonite kasutamise valikulisus lausete lõpetamiseks. Kuigi tungivalt soovituslik, ei ole need kohustuslikud - sellisel juhul paigutab interpretaator programmi käivitudes ise semikoolonid vajalikesse kohtadesse (tavaliselt reavahetuse sümboli asemele). Selline käitumine võib tekitada ootamatuid probleeme - kui interpretaatorile tundub, et lause võiks siinkohal ära lõppeda, siis paigutab ta antud kohta lause lõpetamiseks semikooloni ning käsitleb kõike järgnevat juba uue lausena. Kuna lausetes on eraldajatena lisaks tühikutele lubatud kasutada ka tabulatsioonisümboleid ning reavahetusi, võib selline käitumine lause kergesti valest kohast katkestada. return a+b;

Selles näites oleks korrektne lugeda lauset kujul return a+b;, kuid interpretaator käsitleb seda kui return; a+b;, mis on ilmselgelt vale.

2.3. Tõstutundlik JavaScript on tõstutundlik, mis tähendab et muutujate ja funktsioonide nimedes, samuti tekstiliste väärtuste võrdlemisel, mängivad rolli suur ja väiketähed. Näiteks toString() ei ole sama mis toSTRING(). Samuti ei ole võrdsed tekstid „tere“ ja „Tere“.

2.4. Dünaamiline tüüpimine JavaScript on dünaamiliselt ja nõrgalt tüübitud keel. See tähendab, et tüübikontroll ei toimu kompileerimisel, vaid jooksvalt programmi täitmise jooksul. Tüübid on seotud muutujate asemel väärtustega. Näiteks võib ühe muutuja väärtuseks olla alguses number, hiljem tekst ja lõpuks regulaaravaldise objekt. Praktiliselt suvalist tüüpi väärtust on võimalik operatsioonides kasutada teise tüübi asemel. Sellisel juhul muudetakse väärtus vastavaks nõutule. Näiteks kui meil on funktsioon, mis eeldab sisendiks stringi, aga funktsioonile edastatakse hoopis number, muudetakse number tekstikujule.

2.5. Parditüüpimine „When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck.“ - James Whitcomb Riley (Ameerika kirjanik ja luuletaja 1849-1916). Parditüüpimisel loetakse objekt nõutava tüübiga vastavuses olevat, kui selles on implementeeritud oodatavad meetodid ja omadused. Seda isegi kui objekt on tuletatud mingist komandast konstruktorist. Näiteks kui ootame sisendiks objekti, mis omab meetodit z, siis ei oma meie jaoks tähtsust, kas objekt on loodud konstruktoriga X või Y. KonstruktorX = function(){ this.sisu = 123; }; KonstruktorX.prototype.teade = function(){ 6 / 109


JavaScript, Andris Reinman alert(this.sisu); } var x = new KonstruktorX(); KonstruktorY = function(){}; KonstruktorY.prototype.teade = function(){ alert(Date()); } var y = new KonstruktorY(); function kuva(objekt){ objekt.teade(); } kuva(x); // 123 kuva(y); //Wed May 13 2009 15:06:30 GMT+0300 (FLE Standard Time)

Näites loome kaks erinevat konstruktorit, millega loodud objektidel on olemas meetod teade. Defineeritud funktsioon kuva ootab sisendiks objekti sama nimega meetodiga. Nagu näha, pole vahet mis tüüpi objektiga on tegu, niikaua kuni objektis on nõutud meetod olemas.

7 / 109


JavaScript, Andris Reinman

3. Andmetüübid Kuigi JavaScript on nõrgalt tüübitud keel, ei tähenda see veel, et andmetüübid üldse puuduksid. Tõsi küll - neid tüüpe on suhteliselt vähe. Näiteks numbritüüpe erinevalt keeltest C või Java on ainult üks. Lisaks primitiivsetele tüüpidele nagu number või string, tunneb JavaScript liittüüpi objekt. Objektist aga pärinevad juba mitmed täiendavad keerulisemad andmetüübid nagu massiivid ja funktsioonid. Samuti ka mõningad spetsiaalsed objektitüübid - regulaaravaldise objekt ja kuupäeva objekt. Kõigist neist objekti eri tüüpidest tuleb juttu raamatu hilisemates peatükkides.

3.1. Numbrid Kõik numbrid on JavaScriptis topelttäpsusega 64 bitised ujukomaarvud (IEEE 754). Eraldi tüüpe täisarvude või väiksema täpsusega numbrite jaoks pole - kõiki numbreid, olgu selleks 0 või 10E10 (10×1010) hoitakse mälus ühtemoodi 64 bitise ühikuna. Ainsaks erandiks on bitioperatsioonides kasutatavad numbrid, sellisel juhul teisendatakse number operatsiooni sooritamise ajaks 32 bitiseks. Eritüübilisteks numbriteks on lõpmatus Infinity, mis tekib numbri jagamisel nulliga; negatiivne lõpmatus -Infinity, mis tekib negatiivse numbri jagamisel nulliga; ja mitte-number NaN, mis tähistab kõiki neid väärtusi, mis pole numbrid (sh. nulli jagamine nulliga ja lõpmatuse jagamine lõpmatusega). NaN on huvitav väärtus selle poolest, et ta ei ole võrdne mitte millegagi, sealjuures ka mitte iseendaga (NaN != NaN). NaN väärtuse tuvastamiseks, tuleb kasutada funktsiooni isNaN(väärtus).

3.2. Stringid Stringid on tekstiväärtused mis moodustavad lõpliku 16 bitiste märgita täisarvude järjestatud jada. Eraldi andmetüüp üksiku tähe hoidmiseks (näiteks C keele char) puudub, selle asemel tuleb kasutada tavalist stringi, mille sisuks on vaid üks sümbol.

3.3. undefined undefined

väärtus esineb kui üritatakse kasutada defineeritud, kuid väärtustamata muutujat või objekti olematut omadust. var a; alert(a); // undefined

3.4. null null tähistab olematut väärtust. Tegu on unikaalse väärtusega, mis ei ole sama kui 0, false või undefined kuigi tavalise võrdlustehtega (==) on tulemus tõene. Jäiga võrdlusoperaatoriga (===) võrreldes on tõene ainult väärtuse null võrdlemine väärtusega null. null == false; //true null === false; // false null === null; //true

3.5. Loogilised väärtused Loogilisteks väärtusteks (Boolean) võivad olla väärtused true, mis tähistab tõest ja false, mis 8 / 109


JavaScript, Andris Reinman

tähistab väärat väärtust. Tavaliselt on loogilised väärtused kasutusel erinevates tingimuslausetes, kus vastavalt operaatorite tagastatava loogilise väärtuse tulemuse järgi tehakse erinevaid tegevusi.

3.6. Objekt Objekt (object) on JavaScriptis kõige keerulisem andmetüüp, mis kujutab endast sorteerimata väljade kogumit võtme-väärtuse paaridest. Iga väli võib hoida endas teist objekti, primitiivset väärtust või meetodit. Programmeerimiskeeles Python oleks JavaScripti objektile kõige lähedasem andmetüüp dict ning PHP-s tekstiliste indeksitega massiiv.

3.7. Väärtuste teisendamine operatsioonides Juhul kui mingis operatsioonis üritatakse kasutada oodatust eri tüüpi väärtust, näiteks kasutatakse teksti loogikaväärtuse asemel, teisendatakse väärtus operatsiooni sooritamise ajaks vajalikule kujule. Järgnev tabel näitab ära selliste teisenduste tulemused erinevate väärtuste vahel. Väärtus undefined null Mittetühi string

String "undefined" "null" Nagu on

Tühi string

As is

0 NaN Infinity -Infinity Kõik muud numbrid

"0" "NaN" "Infinity" "-Infinity" Numbri väärtus tekstikujul "true" "false" toString()

true false Objekt

Väärtuse kasutamise kontekst Number Boolean NaN false 0 false Stringi numbriline true väärtus või NaN 0 false Nagu on false Nagu on false Nagu on true Nagu on true Nagu on true 1 0 valueOf(), toString() või NaN

Nagu on Nagu on true

Object Veateade Veateade String objekt String objekt Number objekt Number objekt Number objekt Number objekt Number objekt Boolean objekt Boolean objekt Nagu on

Tabel 1. Väärtuste teisendamine vastavalt kontekstile

3.8. Väärtuste edastamine Primitiivseid tüübid nagu stringid, numbrid jms. edastatakse muutujale omistamisel väärtusena ehk et ühest muutujast väärtuse omistamisel teisele muutujale, saab teine muutuja enda väärtuseks esimese muutuja väärtuse koopia. var a = 12345; var b = a;

Objektid aga edastatakse alati viidana originaalse objekti juurde. Seega eraldiseisvad muutujad ei saa mitte igaüks koopiat samast objektist, vaid ainult viida originaalse objekti juurde. Kui ühe muutuja juures objekti muuta, kehtivad need muutused ka kõigi teiste sama objekti juurde viitavate muutujate jaoks. var a = {}; 9 / 109


JavaScript, Andris Reinman var b = a; b.test = 123; alert(a.test); //123

Objekte on vajadusel siiski võimalik vastavate meetoditega kloonida ning täpsemalt tuleb sellest juttu Objektide peatükis.

3.9. Prahikoristaja JavaScriptis ei ole võimalik programmi käigus ise väärtusi mälust eemaldada. On olemas operaator delete, kuid see ei tühjenda mitte väärtuse poolt hõivatud mälu, vaid ainult viida muutuja ja väärtuse vahel. Kogu vastava mäluhaldusega tegeleb automaatne prügikoristaja, kes aegajalt käivitudes otsib üles programmi käigus väärtuste poolt hõivatud mäluaadressid ja kontrollib nende vastavust muutujatega. Kui ühtegi viidet väärtuse ja muutujate vahelt ei leita, vabastatakse mälu järgmiste operatsioonide jaoks. Üldiselt ei pea programmeerija ise mälukasutuse pärast muretsema, v.a. mõned erijuhud nagu näiteks brauseris DOM elementide sündmuste haldus. Kui eemaldada DOM-ist element, millele on seatud sündmuste haldaja, võib see haldaja elemendi kadumisest hoolimata mällu alles jääda. Juhul kui selline elementide eemaldamine on harvaesinev, siis ei ole veidi suurema mälu hõivamisega suuremat probleemi, aga näiteks veebiaplikatsioonides, kus lehekülgede vahetumist ei toimu ja seega sunnitud mälu vabastamist ei ole, võib brauseri mälukasutus vägagi probleemseks osutuda.

10 / 109


JavaScript, Andris Reinman

4. Operaatorid Operaatorid on erinevad sümbolid ja märgendid, mis võimaldavad JavaScripti programmil teostada mitmesuguseid tegevusi - kontrollida tingimuste vastavust, muuta väärtusi ja muud sellist. Reeglina on operaatoril kaks operandi, vasak ja parem. Näiteks a + b, kus a on operaatori + vasak operand ning b siis vastavalt parem. Eksisteerib ka kolme operandiga operaator (?:, ternaarne tingimuslause) ning ühe operandiga (-, unaarne - või ++ inkrement). Operatsioone saab ka liita. a + b + c - sellisel juhul pole tegu mitte kolme operandiga operatsiooniga vaid kahe liidetud operatsiooniga. Pikemalt saab selle operatsiooni lahti kirjutada nii (a + b) + c;

(kus (a+b) on esimene operatsioon ja (a + b) + c on teine operatsioon) või z = a + b; z + b;

4.1. Aritmeetika 4.1.1. + Liitmistehe m1 + m2; 5 + 2 // 7

Juhul kui üks liidetavatest on string, teisendatakse mõlemad operandid tekstikujule. Sellisel juhul ei liideta operandide numbrilisi väärtusi, vaid liidetakse stringid üksteise järele. Seega tuleb selle tehte juures olla ettevaatlik ning vajadusel teisendada operandid näiteks parseInt funktsiooniga eelnevalt numbriteks. 3 + 4 = 7; "3" + 4 = "37";

Üks situatsioon kus väärtus tuleks kindlasti enne numbrilisi tehteid teisendada, on andmete lugemine veebilehe vormiväljadest. Kõik vormiväljadelt loetud väärtused on alati tekstikujul ning seega nendega väärtustega liitmisel, ilma eelneva teisendamiseta, võib tekkida ootamatuid probleeme. 4.1.2. - - Lahutustehe m1 - m2; 5 - 2 // 3

11 / 109


JavaScript, Andris Reinman

4.1.3. * - Korrutustehe m1 * m2; 5 * 2 // 10

4.1.4. / - Jagamistehe m1 / m2; 5 / 2 // 2.5

Jagamisel nulliga ei ole tulemuseks mitte viga, vaid eritüübiline väärtus +/- Infinity (lõpmatus). 4.1.5. % - Jääk Jäägioperaatorit kasutatakse järgnevalt: m1 % m2, tulemuseks on jääk muutuja m1 jagamisel muutujaga m2. m1 % m2; 5 % 2 // 1

4.1.6. ++ - Inkrement Inkrement ++ suurendab operandi väärtust 1 võrra. Juhul kui operand asub operaatorist vasakul m++, on operatsiooni tagastusväärtuseks esialgne väärtus m (kõigepealt tagastatakse väärtus ja siis liidetakse muutujale 1). Juhul kui operand asub paremal, siis on tagastusväärtuseks m+1 (kõigepealt liidetakse muutujale 1 ning seejärel tagastatakse selle väärtus). var m1 = 0; alert(m1++) // 0; alert(m1) // 1; alert(++m1) // 2;

4.1.7. -- - Dekrement Dekrement -- vähendab operandi väärtust 1 võrra. Juhul kui operand asub operaatorist vasakul m--, on operatsiooni tagastusväärtuseks esialgne väärtus m. Juhul kui operand asub paremal, siis on tagastusväärtuseks m-1. var m1 = 5; alert(m1--) // 5; alert(m1) // 4; alert(--m1) // 3;

4.1.8. Unaarne Muudab väärtuse negatiivseks. -m1;

12 / 109


JavaScript, Andris Reinman

4.2. Omistamine 4.2.1. = - Väärtuse omistamine Operaatorist vasakul olevale muutujale omistatakse operaatorist paremal asuv väärtus. var a = 123;

Järgmised operaatorid on omistamise lühivormid operaatorist vasakul oleva muutuja suhtes. 4.2.2. += - Väärtuse liitmine muutujale x += y; x = x + y;

4.2.3. -= - Väärtuse lahutamine muutujast x += y; x = x + y;

4.2.4. *= - Väärtuse korrutamine muutujale x *= y; x = x * y;

4.2.5. /= - Väärtuse jagamine muutujast x /= y; x = x / y;

4.2.6. >>= - Bittide nihutamine Operaator nihutab bitid muutujas väärtuse võrra paremale, säilitab märgi. x >>= y; x = x >> y;

4.2.7. <<= - Bittide nihutamine Operaator nihutab bitid muutujas väärtuse võrra vasakule, säilitab märgi. x <<= y; x = x << y;

13 / 109


JavaScript, Andris Reinman

4.2.8. >>>= - Bittide nihutamine Operaator nihutab bitid muutujas väärtuse võrra paremale, vasakud bitid täidetakse nullidega. x >>>= y; x = x >>> y;

4.2.9. &= - Bitioperatsioon JA (AND) x &= y; x = x & y;

4.2.10.

|= - Bitioperatsioon VÕI (OR)

x |= y; x = x | y;

4.2.11.

^= - Bitioperatsioon välistav VÕI (XOR)

x ^= y; x = x ^ y;

4.3. Võrdlemine 4.3.1. == - Võrdne Operatsiooni tagastusväärtus on tõene, kui operaatori mõlemad pooled on võrdsed. Juhul kui väärtused on eri tüüpi, teisendatakse kõigepealt tüübid. Kui üks operand on number või loogiline muutuja, teisendatakse operandid numbriteks. Juhul kui üks operand on string, teisendatakse ka teine stringiks. var m1 = 5; m1 == 5 // tõene, 5 == 5 "5" == m1 // tõene, "5" == "5" m1 == '5' // tõene, "5" == "5" m1 == m1 + 0 // tõene, 5 == 5

4.3.2. != - Ei ole võrdne Operatsiooni tagastusväärtus on tõene, kui operaatori pooled ei ole võrdsed. var m1 = 5; m1 != 5 // väär "4" != m1 // tõene m1 == '3' // tõene m1 != m1 + 2 // tõene

14 / 109


JavaScript, Andris Reinman

4.3.3. === - Jäigalt võrdne Operatsiooni tagastusväärtus on tõene, kui operaatori mõlemad pooled on võrdsed ning sama tüüpi. var m1 = 5; m1 === 5 // tõene "5" === m1 // väär m1 === '5' // väär m1 === m1 + 0 // tõene

4.3.4. !== - Jäigalt mittevõrdne Operatsiooni tagastusväärtus on tõene, kui operaatori pooled ei ole võrdsed või on eri tüüpi. var m1 = 5; m1 !== 5 // väär m1 !== '5' // tõene

4.3.5. > - Suurem kui Operatsiooni tagastusväärtus on tõene, kui operatsiooni vasaku operandi väärtus on suurem kui parema operandi väärtus. 5 > 3; // tõene 5 > 5 // väär

4.3.6. >= - Suurem-võrdne kui Operatsiooni tagastusväärtus on tõene, kui operatsiooni vasaku operandi väärtus on suurem või võrdne parema operandi väärtusega. 5 >= 3; // tõene 5 >= 5 //tõene

4.3.7. < - Väiksem kui Operatsiooni tagastusväärtus on tõene, kui operatsiooni vasaku operandi väärtus on väiksem kui parema operandi väärtus. 3 < 5; // tõene 5 < 5 // väär

4.3.8. <= - Väiksem-võrdne kui Operatsiooni tagastusväärtus on tõene, kui operatsiooni vasaku operandi väärtus on väiksem või võrdne parema operandi väärtusega. 3 <= 5; // tõene 5 <= 5 // tõene

15 / 109


JavaScript, Andris Reinman

4.4. Loogilised operaatorid 4.4.1. && - Loogiline JA (AND) Operatsioon on tõene, kui mõlemad operandid on tõesed - sellisel juhul on tagastusväärtuseks viimase operandi väärtus. 3 && 5; //tõene, 5 4 && 0 //väär

Kuna vaadatakse vaid esimese ebatõese operandini, on see hea viis kontrollida mingi alamväärtuse kehtivust. if(a && a.b);

Näites kontrollitakse väärtust a.b ainult juhul, kui a on defineeritud. Kuna kontrollitakse vaid esimese väära operandini, siis tuleb operaatori puhul olla parempoolse operandiga ettevaatlik - sealne avaldis täidetakse vaid juhul, kui vasak operand tagastab tõese väärtuse. Probleem võib tekkida, kui parempoolne operand peab sooritama mingit tegevust iga iteratsiooni ajal. var c = 10, a = false; while(c){ if(a && c--){}; }

Näites olev tsükkel ei jõua kunagi lõpuni, kuna käsk c– jääb alati täitmata. Muutuja a väärtus on false ning seega tingimust edasi ei kontrollita. Samuti tasub ette vaadata tekstiliste väärtustega "0" ning "false" - JavaScripti arvates on nende stringide väärtus võrdlustehetes true, kuigi osad teised keeled, näiteks PHP peavad antud väärtusi samas kontekstis ebatõesteks. 4.4.2. || - Loogiline VÕI (OR) Tagastusväärtus on tõene, kui üks operandidest on tõene. Tagastusväärtuseks on esimene tõene operand. 3 || 5; //tõene (3) 0 || 4; //tõene, 4

Juhul kui vasak operand on tõene, siis parem operand jääb täitmata. Operaatorit || saab kasutada ka mugavaks muutujate lähtestamiseks funktsioonide parameetritena juhul kui väärtus on seadmata, saab muutuja väärtuseks mingi vaikimisi suuruse. function test(nr){ nr = nr || 12; }

Näites kontrollitakse parameeter nr väärtust ning kui seda pole seatud, saab väärtuseks vaikimisi suurus 12. Sama saaks kirjutada ka tingimuslausega if(!nr){nr = 12;} või nr = nr?nr:12, kuid 16 / 109


JavaScript, Andris Reinman

loogilise operaatoriga on lause mugavam kirja panna ning koodi lugedes on see ka kergemini mõistetav. 4.4.3. ! - Loogiline eitus Tagastusväärtus on tõene kui operandi väärtus on väär. !false; //tõene !10 //väär

Operaatoriga ! saab teisendada suvalist väärtust loogiliseks väärtuseks true või false, kui kasutada operaatorit topelt - esimese korraga kontrollitakse, kas väärtust ei eksisteeri ning teise korraga kontrollitakse väärtuse mitte-eksisteerimise eksisteerimist !!10 //tõene, väärtuseks true !!0 //väär, väärtuseks false

4.5. Bitioperatsioonid 4.5.1. & - Bitioperatsioon JA (AND) x = x & y

4.5.2. = - Bitioperatsioon VÕI (OR) x = x | y

4.5.3. ^= - Bitioperatsioon välistav VÕI (XOR) x = x ^ y

4.5.4. ~ - Bitioperatsioon EI (NOT) x = x ~ y

4.5.5. << - Bittide nihutamine vasakule Operaator nihutab bitid muutujas väärtuse võrra vasakule, säilitab märgi. x = x << y

4.5.6. >> - Bittide nihutamine paremale Operaator nihutab bitid muutujas väärtuse võrra paremale, säilitab märgi. 17 / 109


JavaScript, Andris Reinman x = x >> y

4.5.7. >>> - Bittide nihutamine paremale Operaator nihutab bitid muutujas väärtuse võrra paremale, vasakud bitid täidetakse nullidega. x = x >>> y

Bitioperatsioonide kohta loe lähemalt bitioperatsioonide peatükist.

4.6. Tekst 4.6.1. + - Stringide liitmine Juhul kui üks operandidest on string, teisendatab operaator kõik operandid stringideks ning järjestab need stringid üheks kokku. Juhul kui sooviks on siiski liita operande kui numbreid, tuleks stringi kujul number ennem teisendada numbriks funktsiooniga parseInt(). "abc" + "def"; //"abcdef" 3 + "3" // "33"

4.6.2. ''+='' - Stringide liitmise lühivorm var a = "abc"; a += "def"; // a=="abcdef"

4.7. Objektide elemendid 4.7.1. . - Punktnotatsioon Punkt objekti ning elemendi nime vahel tagastab objekti elemendi. var z = document.getElementById('x');

Näites saab muutuja z väärtuseks objektis document oleva meetodi getElementById tagastusväärtus. Kuna punkt on tavaline operaator, siis võib operandide ja operaatori vahel olla ka tühikuid. Mõnel juhul on see isegi kohustuslik - näiteks kui soovime objektina kasutada tavalist numbrit. Selliselt peab numbri ja punkti vahele jääma tühik, kuna vastasel korral peetakse punkti mitte notatsioonioperaatoriks, vaid komakoha eraldajaks. 5.toFixed(2) // SyntaxError 5 . toFixed(2) // "5.00"

4.7.2. [] - Nurksulud Nurksulud objekti nime järel elemendi tekstikujul nimetusega tagastavad objekti elemendi. Sama 18 / 109


JavaScript, Andris Reinman

mis punktnotatsioon, erinevusega et täiendavalt saab kasutada genereeritud elemendi nimetust (elemendi nimetus ei pea olema programmikoodis defineeritud). var z = document['getElementById']('x'); // või var n = 'getElementById'; var z = document[n]('x');

4.8. Spetsiaalsed operaatorid 4.8.1. ?: - Ternaarne tingimuslause (tingimus ? kuiTõene : kuiVäär). tingimus - avaldis, mis tagastab väärtusena tõese true või väära false. kuiTõene ja kuiVäär võivad olla suvalised avaldised. alert( a>b?"a on suurem kui b":"a ei ole suurem kui b");

4.8.2. , (koma) Operaatorina käivitab koma avaldistena mõlemad operandid ning tagastusväärtusena väljastab parempoolse avaldise väärtuse. Operaatorit on kõige parem kasutada olukordades, kus on vaja käivitada mitu avaldist ühe lausena - näiteks for tsükli lähtestamisel. for(var i=0, len=arr.length; i<len; i++);

4.8.3. delete Operaator delete kustutab objekti, objekti elemendi või massiivi kindlal indeksil asuva elemendi, v.a. need muutujaid, mis on deklareeritud käsuga var. Operaator delete kustutab tegelikult muutuja väärtuse asemel ainult viite selle väärtuse juurde, väärtust ennast ta ei eemalda. Väärtuse tegelikuks kustutamiseks on JavaScriptis olemas „prügikoristaja“ (garbage collector), mis käivitudes kustutab mälust kõik väärtused, mille juurde ei ole ühtegi töötavat viidet. Seega programmeerija ei pea ise muretsema kasutuks muutunud objektide eemaldamise pärast. a = {sisu: "see on objekt"}; b = a; delete a; alert(b.sisu); // "see on objekt"

Antud näites „kustutasime“ küll esialgse objekti, kuid tegelikult kadus vaid esialgne viide objekti juurde. Hiljem loodud viide b = a jäi siiski kasutatavaks. 4.8.4. in Elemendi olemasolu kontroll objektis. „element“ in objekt väljastab tõese tagastusväärtuse juhul kui objektis on olemas element või numbriline indeks nimega „element“. if ("getElementById" in document){ document.getElementById("elemendi_id"); 19 / 109


JavaScript, Andris Reinman }

4.8.5. instanceof Objekti tüübi vastavuse kontroll. objekt instanceof tyyp väljastab tõese tagastusväärtuse juhul kui objekti tüüp on tyyp. new String("abc") instanceof String //true

4.8.6. this Viide hetkel aktiivsele objektile, meetodi sees viitab this kutsuvale objektile. var Auto = function(mark){ this.mark = mark; // this viitab hetkel aktiivsele funktsioonile Auto } Auto.prototype.getMark = function(){ return this.mark; // Kuna tegu on meetodiga, viitab this meetodi omanikule - funktsioonile Auto } var auto = new Auto('Audi'); alert(auto.mark); // Audi alert(auto.getMark()); // Audi this

võib tekitada probleeme sulundite korral - kui objekti sees on defineeritud anonüümne funktsioon, on selle anonüümse funktsiooni this viiteks mitte väline objekt, vaid hoopis globaalne objekt window. Anonüümsele funktsioonile saab õige viite edastada läbi mõne muutuja, mis on defineeritud välise objekti skoobis. var Auto = function(mark){ this.mark = mark; var that = this; (function(){ alert(that.mark); // anonüümses funktsioonis viitab this enesele, kasutada tuleb välise skoobi muutujat })(); // pane tähele lõpetavaid sulge, mis käivitavad esimestes sulgudes tagastatud anonüümse funktsiooni } new Auto('Toyota'); // Toyota

Teine võimalus on siduda this sulundfunktsiooniga läbi funktsiooni meetodi apply või call (loe lähemalt funktsioonide peatükist). var Auto = function(mark){ this.mark = mark; (function(){ alert(this.mark); // seekord on this "õige" }).apply(this); } new Auto('Toyota'); // Toyota

20 / 109


JavaScript, Andris Reinman

4.8.7. typeof Väljastab avaldise tüübi stringi kujul. typeof "tekst" // "string"; typeof 2 // "number"

4.8.8. void Käivitab etteantud avaldise ning väljastab tulemusena undefined. Avaldise parameeter on kohustuslik. void (a = 2); void; // SyntaxError, parameeter on kohustuslik

4.8.9. new Konstruktoroperaator, mis loob paremal olevast objektist uue instantsi ning omistab vasakul olevale muutujale loodud instantsile suunatud viite this. var objekt = new Konstruktor(); var aeg = new Date();

4.8.10. Kommentaarid Kommentaarid on koodiblokid, mille interpretaator jätab vahele ning mida on mugav kasutada programmi töö kohta selgituste lisamiseks. // kommenteerib rea lõpuni, lõpetavat märgendit ei vaja /* kommenteerib kuni kommentaari lõpetava märgendini */

Erinevad minimeerimisprogrammid, mis on mõeldud JavaScript failide suuruse vähendamiseks (vähendamaks serveri koormust failide laadimisel), kustutavad kommentaarid koodist automaatselt ise ära.

4.9. Operatsioonide järjekord Erinevate operatsioonide korral ühes lauses tekib alati küsimus, missugune operatsioon nendest kõigepealt teostatakse? Näiteks kas lauses a + 4 / 5 teostatakse esiteks kõige vasakpoolsem st. esimene operatsioon lauses (+) või mingi muu (/). Allolevast tabelist leiabki vastava järjestuse, kus eelistuse number näitab järjekorda mille alusel erinevaid operatsioone koheldakse. Mida väiksem number, seda eelistatum operatsioon teistega võrreldes on. Eelnenud näites oleks seega esimeseks operatsiooniks jagamine / (5) ja teiseks liitmine + (6). Eelistus 1 1 2 3 3

Operatsioon objekti element uus objekt funktsiooni käivitus inkrement dekrement

Operaatorid ., [] new () ++ – 21 / 109


JavaScript, Andris Reinman 4 4 4 4 4 4 4 5 5 5 6 6 7 8 8 8 9 10 11 12 13 14 15 16 17

loogiline NOT bitioperaator NOT unaarne + unaarne tüübi kontroll tühi muutuja kustutamine korrutustehe jagamistehe jäägi leidmine liitmistehe jagamistehe bittide nihutamine väärtuste suhted elemendi kontroll objektist isendi konstruktori kontroll väärtuste võrdsus bitioperatsioon JA (AND) bitioperatsioon välistav VÕI (XOR) bitioperatsioon VÕI (OR) loogiline JA (AND) loogiline VÕI (OR) ternaarne tingimuslause omistamine koma

! ~ + typeof void delete * / % + <<, >>, >>> <, <=, >, >= in instanceof ==, !=, ===, !== & ^ | && || ?: =, +=, -=, *=, /=, %=, <<=, >>=, >>>=, &=, ^=, |= ,

Tabel 2. Operaatorite järjekord

22 / 109


JavaScript, Andris Reinman

5. Keele struktuurid Javascripti süntaks ning keele struktuurid on praktilised identsed C, Java, PHP ja muude sarnaste programmeerimiskeeltega. Nii tsüklid kui tingimuslaused peaksid seega olema kõigile varem taolisi keeli kasutanutule tuttavad. Erandiks oleks ehk vaid for..in, mis tuleneb peamiselt JavaScripti prototüübilisest ülesehitusest ning mida seetõttu muudes keeltes võibolla päris sellisel kujul ei esine.

5.1. Tsüklid Tsükkel ehk korduslause on programmiosa, mis kordab määratud lausejada senikaua kuni etteantud tingimus saab täidetud. Näiteks kui on vaja mingisugust tegevust korrata teatud kindel arv kordi (selleks sobib hästi for tsükkel) või kuni kindel tingimus saab täidetud (while ja do..while). Tüklite peamiseks probleemiks on, et tsükli täitmise ajal on kogu programmi kontroll tsükli käes, sh. programmi brauseriaknas täitmise korral ka kontroll brauseri üle. See tähendab, et kui mingi tsükkel töötab liiga kaua (näiteks lõputu tsükkel), siis reeglina muutub brauseri aken mittevastavaks. Eesolevalt veebilehelt ei saa ära navigeerida, ei saa brauseri akent sulgeda, ei saa skripti tööd peatada. Tegevus võib lõppeda terve arvuti kinnijooksmisega, kui brauseris jooksev skript kulutab ära kogu arvuti CPU ning mälu limiidid. Seega tuleb hoolega jälgida, et ei tekiks programmis võimalust sarnase olukorra tekkimiseks. Lõputu tsükli näide: while(1){}

Tsüklit täidetakse seni, kuni 1 ei ole enam tõene (1==0), seda ei juhtu paraku aga kunagi. 5.1.1. for for tsükkel on loendajaga tsükkel. Tsüklit täidetakse seni, kuni loendajaga seotud tingimus enam ei kehti (n: loendaja saab suuremaks lubatud väärtusest). Tsükkel kasutab järgmist süntaksit:

for (lähtesta; tingimus; muutus) { // korda kuni 'tingimus' enam ei kehti }

Näiteks:

for (i=0; i<array.length; i++) { alert(array[i]); }

Eelmine näide ei ole tegelikult for tsükli iseloomustamiseks eriti hea. Esiteks on muutuja i ise lähtestamata - sellisel juhul lülitatakse see globaalsesse skoopi, mis võib viia ootamatute tulemusteni. Teiseks tuleb tsükli iga korduse puhul leida üles massiivi suurus (suurim indeks+1). Veidi paremini koostatud tsükkel oleks selline: for(var i=0, len=array.length; i<len; i++){ 23 / 109


JavaScript, Andris Reinman alert(array[i]); }

Ja kolmas implementatsioon oleks (eeldame et massiivi kõik liikmed on tõesed väärtused): for (var i=0; item=array[i]; i++) { alert(item); }

Sellisel juhul pole massiivi pikkust vaja üldse teada. Tsükkel kestab seni, kuni massiivi elemendi väärtus ei ole tõene. 5.1.2. for..in for..in struktuur on etteantud massiiviga seotud tsükkel, mis väljastab ükshaaval massiivi kõik indeksid. for (indeks in massiiv) { // väljastab ükshaaval kõik indeksid }

Näiteks: for (var a in array) { alert(array[a]); }

Kahjuks ei ole sellisel viisil väljastatud indeksite järjestus garanteeritud - massiivi koheldakse for..in tsüklis objektina, aga objekt kujutab endast sorteerimata kogumit. Samuti võib tekkida probleeme, kui tegu pole lihtsa massiiviga - kuna operaator in on mõeldud objektidest (JavaScripti järgi on massiiv eritüübiline objekt) võtmete leidmiseks, võib tsükkel seetõttu väljastada lisaks numbrilistele indeksitele ka muid konkreetse objekti juurde käivaid võtmeid. var array = [1,2,3]; array.suvaline = function(){ // lisame massiivile meetodi nimega suvaline alert(this.length); }; for(var a in array){ alert(a); }

Väljastab: 0 1 2 suvaline

5.1.3. while while tsükkel on eelkontrolliga tsükkel, mis tähendab, et tsüklit täidetakse seni kuni tsüklitingimus võtmesõna while järel ei ole enam tõene. while tsükli süntaks on järgmine: 24 / 109


JavaScript, Andris Reinman while (tsüklitingimus) { // korda kuni 'tingimus' enam ei kehti }

5.1.4. do do tsükkel on järelkontrolliga tsükkel - tsüklit täidetakse seni kuni tsüklitingimus võtmesõna while järel ei ole enam tõene. Tsükkel erineb eelkontrolliga while tsüklist selle tõttu, et tsüklit täidetakse sama tsüklitingimuse korral ühe korra rohkem kuna kontroll ei ole mitte tsükli alguses, vaid lõpus. while tsükkel mittetõese tingimuse korral ei rakendu, aga do tsükkel rakendub vähemalt korra. Tsükli süntaks on järgmine: do {

// korda kuni 'tingimus' enam ei kehti } while (tsüklitingimus);

5.2. Tingimuslaused Tingimuslaused võimaldavad käivitada või vahele jätta tegevusi vastavalt sisendparameetrite väärtustele. 5.2.1. if Tingimuslause, mis sõltuvalt tingimusavaldise tõeväärtusest kutsub esile lisatud lausejadade täitmise või jätab need vahele. Tingimusavaldis if lauses peab asuma sulgudes. if (tingimus) { // täida, kui tingimus on tõene } else { // täida kui tingimus ei ole tõene }

else

lausejada ei ole kohustuslik.

JavaScriptis puudub programmeerimiskeelte PERL elsif, PHP elseif ja Python elif käsklustele sarnane tingimuslause. Selle asemel võib kasutada if tingimuslausete liitmist või hoopis käsklust switch. if

tingimuslausete liitmine erinevate väärtuste kontrollimiseks:

if (a==0) { // täidetakse juhul kui a on võrdne väärtusega ''0'' } else if (a<10) { // täidetakse juhul kui a on väiksem kui ''10'' } else { // täidetakse kõikidel muudel juhtudel }

5.2.2. Ternaarne tingimuslause Ternaarne operatsioon on kolme operaatori funktsioon if..else tingimuslause esitamiseks 25 / 109


JavaScript, Andris Reinman

lühivormina. Tingimuslause argumendid on üks loogiline muutuja (tingimus) ja kaks lauset ning selle tagastusväärtuseks on esimese lause tagastusväärtus, kui tingimus on tõene, ja teise lause tagastusväärtus, kui tingimus on väär. Operaatoriteks on sümbolid ? ning :. tingimus?tagastus_tõese_tingimuse_korral:tagastus_väära_tingimuse_korral;

var a = b>1?2:3;

Juhul kui muutuja b on näites suurem kui 1, saab muutuja a väärtuseks 2, vastasel juhul aga saab muutuja väärtuseks 3. 5.2.3. switch switch on valikulause mitmevariandiliste valikute realiseerimiseks. switch (väärtus) { case tingimus: //täida kui tingimus vastab sisendväärtusele break; //keelab järgnevaid tingimusi proovida default: //täida kui ükski tingimus ei olnud sisendväärtuse suhtes tõene (ei ole kohustuslik) }

Valiklause switch puhul leitakse esiteks võtmesõna switch järel oleva avaldise väärtus. Seejärel võrreldakse saadud väärtust võtmesõnade case järel olevate avaldiste väärtustega ning kui väärtused on võrdsed, täidetakse järgnev lausejada. Käsklus break lõpetab valiklause täitmise. Juhul kui break puudub, täidetakse ka järgmine avaldis, hoolimata selle case kontrollväärtusest. Kui ei leita ühtegi tõest case tingimust, täidetakse (juhul kui on) valikuline default lausejada. switch (a) { case 0: alert('a on 0'); break; case 1: alert('a on 1'); break; case 2: alert('a on 2'); break; default: alert('a ei ole 0 ega 1 ega 2'); }

5.3. Veatöötlus JavaScript pakub arendajale mitmeid võimalusi tekkivaid vigu hallata. Üheks selliseks võimaluseks on näiteks sündmusele onError oma sündmuse haldaja lisamist, mis võimaldab „ära lõigata“ kõik tekkivad vead. Mõistlikum oleks siiski läheneda vigadele ükshaaval. 5.3.1. try..catch try..catch on lausestruktuur, mis võimaldab proovida mingi lausejada täitmist (try) ning kui selles esineb viga, tühistatakse kõik lausejada tegevused ja täidetakse veatöötluse käsklused (catch). try{ 26 / 109


JavaScript, Andris Reinman // Proovi mingeid tegevusi } catch (E) { // Juhul kui tegevused päädisid vea ilmnemisega, käivita antud blokk // muutuja E sisaldab endas infot tekkinud vea kohta }

Näiteks: try{ var a = tundmatu_suurus; // tundmatu suurus on defineerimata }catch(E){ alert(E.message); }

Väljundiks on: tundmatu_suurus is not defined

5.3.2. throw throw lõpetab programmi täitmise ja väljastab veateate. Saab kasutada koos try..catch struktuuriga, kus try lausejadas olev tingimus käivitab throw ja lõpetab sellega lausejada täitmise. throw "veateade";

Näiteks: try{

if(1!=2){ throw new Error("1 ja 2 ei ole võrdsed!"); } } catch (E) { alert(E.message); }

Väljund: Viga! 1 ja 2 ei ole võrdsed!

5.4. Muud lausestruktuurid 5.4.1. label Märgend label võimaldab ära tähistada programmiosi, millele saab viidata lausetega break ning continue. Märgendiks võib olla suvaline nimetus mis ei kuulu reserveeritud sõnade hulka. Oluline on, et label omab tähendust vaid vahetult märgendile järgnevas lauses, milleks võib muu hulgas olla ka {} blokk. Muudest programmiosadest label blokki välja kutsuda ei saa - selle poolest erineb märgend näiteks basicu GOTO lausest. 27 / 109


JavaScript, Andris Reinman

Käsklus break katkestab märgendile järgneva lause ning programm saab oma tööga edasi minna. continue aga viib programmi täitmise märgendi juurde tagasi, moodustades sellega omamoodi tsükli. Märgendite kasutamine ei ole siiski väga soovituslik programmeerimisstiil, kuna võib muutuda raskesti jälgitavaks ning seega võivad vead kergemalt sisse sattuda. var loendur = 0; kordus: { // märgend while(1){ // Lõputu tsükkel alert(loendur); loendur++; if(loendur>10) // juhul kui loendur on suurem kui 10, lõpetame märgendiga tähistatud lausejada break kordus; } }

5.4.2. break Katkestuslause break [label]; peatab tsükli, valikulause switch või märgendlause label täitmise. Katkestuslause peab asuma katkestatava lausejada sees. Parameeter label on valikuline ning kasutatav juhul, kui soovitakse lõpetada märgendatud lausejada täitmist (vt. label). while(1){ break; //katkestab tsükli while }

5.4.3. continue Jätkamislause continue [label]; sarnaneb katkestuslausele break, aga kui break katkestab hetke lausejada täitmise üldse, siis continue lõpetab ainult hetkel käimasoleva iteratsiooni ning läheb järgmise iteratsiooniga edasi. Võimalik on niiviisi katkestada tsükleid ning juhul kui valikuline parameeter label on määratud, ka märgendlauseid. for(var i=0; i< len; i++){ alert(i); // Seda rida täidetakse nii palju kordi, kui on muutuja len suurus. continue; // Liigutab programmi täitmise järgmise for iteratsiooni juurde alert(i); // Seda rida ei täideta kunagi }

5.4.4. function Loob uue funktsiooni etteantud parameetritega, täpsemalt loe funktsioonide peatükist. function a(x){ alert(x); }

28 / 109


JavaScript, Andris Reinman

5.4.5. return return [väärtus]; määrab ära funktsiooni poolt tagastatava väärtuse, milleks on valikulise parameetri väärtus väärtus. Juhul kui parameeter väärtus pole määratud, käitub lause sarnaselt lausele break tsüklite korral ning funktsiooni töö lõpetatakse, tagastades väljastuskohta eriväärtuse undefined (sama väärtus tagastatakse ka juhul, kui return lause puudub üldse). function liida(a, b){ return a+b; }

5.4.6. var var deklareerib muutuja hetke skoobis ning kui on vastavalt määratud, siis ka lähtestab. var m1 [= v1], m2 [= v2],… mn [= vn];, kus mx on muutuja ning vx on väärtus. var a; var a=0; var a=0, b=7;

var

lausega tuleb kindlasti jälgida skoopi - JavaScript erinevalt teistest C sarnase süntaksiga programmeerimiskeeltest ei oma mitte blokk-, vaid funktsiooni skoopi. Ehk et var lause omab muutuja kohta tähendust ühe korra globaalses skoobis ning siis veel korra igas funktsioonis eraldi. Juhul kui skoobis on deklareeritud muutuja võtmesõnaga var, muudab see muutuja lokaalseks terve skoobi ulatuses. Loe lähemalt funktsioonide peatükist. var a=1; { var a=2; } alert(a); // väljastab 2 var a=1; (function(){ var a=2; })(); alert(a); // väljastab 1 }

5.4.7. with Võtmesõna with lühendab objekti jada lausejadas - võimalik on näiteks kasutada pika nimetuse objekt.alamobjekt.veel.muutuja asemel lühikest nimetust muutuja. Seega saab kirjutada document.getElementbyId('elemendi_id').style.color = 'red'; document.getElementbyId('elemendi_id').style.background = 'black';

asemel 29 / 109


JavaScript, Andris Reinman with(document.getElementbyId('elemendi_id').style){ color = 'red'; background = 'black'; }

Seda võtmesõna ei tasu siiski mitte kunagi kasutada, kuna with on lõppematu vigade allikas. Probleem seisneb selles, et with järgi olev lausejada jagab ümbritsevat skoopi ning seega ka kõiki kättesaadavaid muutujaid. Programmikoodi lugedes pead täpselt teadma, et kas color on document.getElementbyId('elemendi_id').style juurde käiv element või hoopis mõni globaalne muutuja. Ei ole võimalik üheselt aru saada, millised muutujad lausejadas tulevad väljast ja millised seotud objekti juurest. Vigade avastamise ja likvideerimise teeb see ülimalt raskeks. Mõistlikum oleks kasutada objekti omistamist uuele muutujale (muutujaid omistades ei looda kunagi omistatavast muutujast koopiat vaid antakse uuele muutujale viide vana juurde, seega omistamisega täiendavat ressursikulu ei kaasne). var o = document.getElementbyId('elemendi_id').style; o.color = 'red'; o.background = 'black';

30 / 109


JavaScript, Andris Reinman

6. Funktsioonid Funktsioon on alamprogramm, mis tekitab väljakutsekohta tagastatava andmeväärtuse. Funktsioon on korduvkasutatav ehk väljakutsutav erinevatest programmi osadest, vähendades sellega programmi loomise ajakulu, haldamise vaeva ja koodi pikkust. Funktsiooni käivitades peatatakse hetkel aktiivne programmi osa ning antakse järg üle käivitatavale funktsioonile. Kontroll taastub peale käivitatud funktsiooni töö lõpetamist. JavaScript käsitleb funktsioone kõrgemat-järku objektidena. See tähendab, et funktsioone saab luua programmi töötamise ajal, funktsioone saab sarnaselt teistele väärtustele omistada muutujatele, neid saab edastada teiste funktsioonide parameetritena, saab tagastada mingi tegevuse tulemusena jms. Sellise funktsioonidega opereerimise korral ei ole tegu mitte funktsiooni poolt tagastatava väärtuse omistamise ja liigutamisega, vaid funktsiooniobjekti endaga. Kui funktsioon omistada mõnele muutujale väärtuseks, siis see muutuja muutub ka ise käivitavaks. Kui lihtsamad objektid on seotud Object.protoype prototüübiga, siis funktsioonid on lingitud Function.prototype prototüübiga. Viimane omakorda on aga lingitud Object.prototype prototüübi külge. Seega on ka funktsiooni korral tegu objektiga. Funktsiooni eristab muudest objektidest vaid omadus, et funktsiooni saab käivitada. Käivitamiseks tuleb lisada funktsiooni (võib olla suvaline avaldis, mis tagastab väärtusena funktsiooniobjekti) järele täitmist märkivad sümbolid - sulud. var ƒ = func. // ƒ on muutuja, mille väärtuseks on objekt - funktsioon - func. ƒ(); // lisades käivitamise sümbolid (), käivitub muutujas ƒ salvestatud funktsioon

6.1. Deklareerimine Funktsiooni saab deklareerida kahel viisil - funktsiooni deklareerimise läbi ning lambda-avaldise kujul funktsiooni literaalina anonüümse funktsiooni omistamisega muutujale. function nimi ([p1,...[,pn]]) { // Funktsiooni sisu }

[var] nimi = function [nimi] ([p1,...[,pn]]) { // Funktsiooni sisu };

Kuna funktsiooni literaali korral on tegu väärtuse omistamisega muutujale, oleks korrektne kasutada siin lause lõpetamiseks semikoolonit. Funktsiooni defineerimiseks on ka kolmas viis, kasutades funktsiooni Function(): var nimi = Function(["p1",...[,"pn"]], "funktsiooni sisu tekstina");

Näiteks: var nimi = Function("number","alert(number);"); 31 / 109


JavaScript, Andris Reinman nimi(123); // 123

Näidatud kolmandat varianti ei ole soovitatav võimalusel mitte kunagi kasutada. Function toetub käsklusele eval, mis tähendab, et selle realiseerimine on suhteliselt aeglane ning mis kõige halvem - seda on praktiliselt võimatu siluda, vead kipuvad aga kergelt tekkima.

6.2. Funktsiooni käivitamine Funktsiooni saab käivitada suluoperaatoriga, lisades operaatori () funktsiooni nime järele. Sulgudes asuvad väärtused edastatakse funktsioonile sisendparameetritena. alert (123);

Võimalik on käivitada ka anonüümseid funktsioone, mis ei kuulu ühegi muutuja juurde. Selle jaoks tuleb funktsiooni deklaratsioon ümbritseda sulgudega ning sulgude poolt tagastatud väärtust saab omakorda järgmiste sulgudega käivitada - esimesed sulud käituvad sellisel juhul vastavalt kontekstile tagastusoperaatorina, mis tagastavad nende sees oleva avaldise väärtuse (selleks on funktsiooniobjekt) ning teised sulud käituvad käivitusoperaatorina, käivitades operaatorist vasakul asuva funktsiooni. (function(i){ alert(i); })(123); //123

Sellist anonüümsete funktsioonide käivitamist kasutatakse tavaliselt uue skoobi loomiseks. Kuna skoop JavaScriptis on ainult funktsioonisisene, mitte suvaline {} blokk, võib taoline kunstlik skoobi loomine mõningatel juhtudel - näiteks vältimaks globaalse skoobi „reostamist“ kohalike muutujatega - vajalikuks osutuda.

6.3. Sisendparameetrid Funktsiooni defineerimisel saab määrata ära ka funktsiooni sisendparameetrid, milleks võib olla suvaline arv muutujaid. Formaalsete parameetrite (määratud funktsiooni deklaratsioonis) kasutamine ei ole siiski kohustuslik. Juhul kui on defineeritud näiteks sisendparameeter x, aga seda reaalselt funktsioonile edastatud pole, on funktsiooni skoobis x väärtuseks undefined. function a(x){ alert(x); } a(); // Väljastab: undefined

Lisaks defineeritule edastatakse funktsioonile veel kaks täiendavat parameetrit - arguments ja this, mis on eritüübilised muutujad. arguments sisaldab massiivi kujul kõiki sisendparameetreid ning this on viide aktiivsele objektile, mille juurde funktsioon kuulub. Täpsemalt saab this kohta lugeda objektide peatükist. Vaikimisi on this väärtuseks globaalne objekt window, objekti meetodi korral aga objekt mille meetodiks funktsioon on. function a(){ var sum = 0; for(var i=0, item=0; item = arguments[i]; i++){ sum += item; // Liidame kõik sisendparameetrid ükshaaval kokku } 32 / 109


JavaScript, Andris Reinman alert(sum); } a(1,2,3,4); // 1+2+3+4 = 10

arguments

parameeter ei ole tegelikult massiiv, kuigi ta seda paistab. arguments on massiivilaadne objekt. Sellel on olemas küll meetod length massiivi elementide arvu leidmiseks, kuid puuduvad kõik teised massiividega seotud meetodid (push, shift jms.). var len = arguments.length;

Täiendavalt omab arguments parameeter atribuuti callee, mis tähistab funktsiooni ennast. Kui this viitab hetkel aktiivsele objektile, siis arguments.callee on sünonüüm funktsiooni nimega. Kasutada saab seda rekursiivsete funktsioonide korral. function a(b, z){ z = z || 1; // juhul kui z väärtus puudub, saab vaikimisi väärtuseks 1 alert(z); if(z++<b){ arguments.callee(b,z); // käivitame funktsiooni a uue z väärtusega // sama mis a(b,z); } } a(10); // väljastab ükshaaval numbrid 1-10

Vajadusel saab arguments pseudomassiivi teisendada massiiviks läbi massiivi prototüübi meetodi slice() var args = Array.prototype.slice.call(arguments);

Sellisel juhul kutsume välja massiivi prototüübis paikneva meetodi, seades funktsiooni meetodiga call hetke objekti viiteks arguments pseudomassiivi. Kuna meetodil slice on sisendparameetrid määramata, kaastakse kõik hetke massiivi elemendid (0 .. arguments.length) ning tagastatakse need uue massiiviobjektina.

6.4. Tagastus Töö lõpetamisel tagastab funktsioon väljakutsekohale väärtuse võtmesõnaga return. Juhul kui funktsioon lõpetab tegevuse enne võtmesõna return ilmnemist või see puudub sootuks, tagastatakse väljakutsekohta väärtus undefined. Erandjuhuks on konstruktor new - kui funktsioon täidetakse koos vastava võtmesõnaga, tagastatakse viit loodud objekti juurde. Lisaks väärtuse tagastamisele saab võtmesõna return kasutada ka funktsiooni töö sunniviisiliseks lõpetamiseks kuna ühtegi rida peale return-i enam ei täideta. function a(z){ return z+2; 4+5; // Seda rida ei täideta mitte kunagi }

33 / 109


JavaScript, Andris Reinman

6.5. Skoop Skoop on programmiosa kehtivuspiirkond milles deklareeritud muutujad omavad väärtust ainult selles piirkonnas - väljaspoolt skoopi muutujate väärtuseid lugeda ega muuta pole võimalik. Erinevalt paljudest teistest C sarnase süntaksiga programmeerimiskeeltest, omavad JavaScriptis skoopi ainult funktsioonid, mitte kõik {…} blokid. JavaScript käsitleb käivitatud funktsiooni skoobina mitte väljakutsekohta, vaid kohta, kus funktsioon on defineeritud. Üksteise sees defineeritud fuktsioonid moodustavad skoobiahela, milles sisemine skoop saab enda käsutusse kõik välises skoobis kehtivad omadused ja meetodid. Skoobisisese muutuja saab deklareerida võtmesõnaga var. funtion z(){ var t = 123; }

// muutuja t on ligipääsetav ainult funktsiooni z skoobist

z(); // Käivitame funktsiooni z, mis annab omas skoobis muutujale t väärtuse 123 try{

t; }catch(E){ alert(E.message); // t is not defined }

Meeles tuleb pidada, et märksõna var kasutamine skoobis suvalises kohas muutuja märgistamiseks, muudab muutuja terve skoobi jaoks lokaalseks. Seega üllatuste ärahoidmiseks tasub muutujad deklareerida mitte jooksvalt skoobi sees, vaid skoobi alguses. t=1; function z(){ t++; var t = 123; } z();

Võiks arvata, et funktsiooni z() esimene rida t++; määrab muutuja väärtuseks 2 (1+1), kuna skoobisisene lähtestamine tuleb alles järgmisel real var t = 123;. Tegelikult aga saab muutuja t väärtuseks NaN (undefined + 1). Seega tuleb arvestada, et var deklaratsiooni positsioon skoobis pole oluline - muutuja on var asukohast hoolimata skoobis läbivalt lokaalne - ning selle teadmise ignoreerimine võib viia raskesti avastatavate vigade tekkimiseni.

6.6. Lokaalne skoop Kuigi keeleliselt lokaalset skoopi JavaScriptis ei eksisteeri (olemas on vaid funktsiooni skoop), on see saavutatav läbi anonüümsete funktsioonide kasutamise. function z(){ (function(){ var t = 2; alert(t); // 2 })() alert(t); // ReferenceError, t on defineerimata }

34 / 109


JavaScript, Andris Reinman

Näites on lokaalseks skoobiks anonüümne funktsioon mida täidetakse kohapeal. Sulud operaatorina käituvad vastavalt kontekstile - esimesed sulud tagastavad nende sees defineeritud funktsiooni ning tagastuskohale järgnevad sulud sunnivad selle funktsiooni käivitamisele. Taoline anonüümne funktsioon saab läbi sulundi kätte kõik välimise funktsiooni muutujad, kuid kohapeal defineeritud muutujatele väljast enam ligi ei pääse. Objekti meetodite sees, säilitamaks viidet this, on mugav kasutada funktsiooni meetodit call. Sellega seome anonüümse funktsiooni objektiviite hetkel aktiivse objektiga ning ei ole vaja muretseda selle viite kadumise pärast. var z = {a: 2}; z.meetod = function(){ (function(){ var t = 2 * this.a; alert(t); // 4 }).call(this) alert(t); // ReferenceError, t on defineerimata }

6.7. Sulundid JavaScripti funktsioonid on kõrgemat-järku objektid, mis tähendab, et funktsiooni skoobis saab defineerida siseseid täiendavaid funktsioone. Neid siseseid funktsioone saab omakorda käivitada, omistada muutujatele väärtuseks või tagastada võtmesõnaga return välise funktsiooni tagastusväärtusena. Defineeritud sisemised funktsioonid omavad ligipääsu lisaks enda skoobis olevatele väärtustele ja objektidele ka funktsiooni loonud välise funktsiooni skoobi väärtustele ja objektidele. Sellisel viisil ühendatud skoobid moodustavad sulundi. Sulundi näide: function generaator(){ var i = 0; return function(){ return i++; } } genereeri = generaator(); genereeri(); // 0 genereeri(); // 1 genereeri(); // 2

Funktsiooni generaator() skoobis asub lokaalne muutuja i, mille algväärtus on 0. Tagastatav sisemine anonüümne funktsioon kasutab tekkinud sulundi võimalusena välise funktsiooni muutujat enda andmete salvestamiseks. Seega iga funktsiooni genereeri käivitamisega muudetakse välise funktsiooni muutuja i väärtust ning tagastatakse see väljakutsekohta. Funktsiooni saab deklareerida teise funktsiooni sees ainult funktsiooni peamises blokis, mitte sisestes (näites for lause blokis vms.). Funktsiooni literaale aga saab seada igal pool. function master(){ // alamfunktsiooni deklareerimine function slave(){ // funktsiooni sisu

35 / 109


JavaScript, Andris Reinman } for(var i=0; i<10; i++){ // funktsiooni literaal var literaal = function(){ return i*i; } alert(literaal()); }

} master();

6.8. Rekursioonid JavaScript võimaldab funktsioonide rekursioone - funktsioon saab kutsuda välja iseennast. Rekursiooni näide: function z (x, i){ var i = i || 0; if(i<10){ alert(x); z(x, ++i); } } z("tere maailm!");

Kui i väärtus funktsioonis z() on väiksem kui 10, siis funktsioon kutsub end ise uuesti välja koos 1 võrra suurema i väärtusega. Funktsiooni z(x) käivitamise tulemuseks kuvatakse ekraanil 10 korda muutuja x väärtus, milleks näites on „tere maailm!“. Funktsioon saab kutsuda iseennast kas oma nime abil või parameetri arguments meetodiga callee. function a(){ a(); } function b(){ arguments.callee(); }

Lihtsamad rekursioonid saab asendada tsüklitega ja see on ka soovitatav praktika, kuna rekursioonid võivad intensiivsemal kasutamisel osutuda vägagi ressursivaenulikeks. Keerulisematel juhtudel kus on näiteks vaja toimetada teadmata suurusega puukujuliste objektidega (DOM), võib tsüklite kasutamine olla üsna keeruline, rekursiooniga aga saab suhteliselt lihtsalt selliseid probleeme lahendada. Järgmises näites kasutame rekursioone numbrite liitmisel. Koostame funktsiooni, mis võtab suvalise arvu parameetreid ja liidab nende väärtused kokku. Massiivist liidetava puhul summeeritakse eelnevalt massiivi elemendid rekursiooni abil, kutsudes hetke funktsiooni välja nii, et kutsutava funktsiooni parameetriteks oleksid massiivi elementide väärtused. function sum(){ var summa = 0; for(var i=0, len = arguments.length; i<len;i++){ // juhul kui parameeter on number, liidame selle koheselet if(typeof arguments[i] == 'number'){ 36 / 109


JavaScript, Andris Reinman summa += arguments[i]; } // massiivi puhul kutsume funktsiooni uuesti välja if(arguments[i].constructor == Array){ // meetod apply esitab massivi elemendid eraldi parameetritena // func.apply(this,[1,2,3]) == func(1,2,3); // lisaks määratakse ka nõutud viit this, mis hetkel küll ei ole aktuaalne summa += arguments.callee.apply(this, arguments[i]); } } return summa; } alert(sum(1,2,[3,4,[5,6]])); // 21 (1+2+3+4+5+6)

Järgmise näitena vaatame ükshaaval läbi kõik puukujulise objekti (näiteks dokumendiobjektimudel DOM, või XML objekt) elemendid function jalutaPuu(haru) { if (haru == null) // return; // tee midagi puu haruga for (var i = 0; i < haru.childNodes.length; i++) { jalutaPuu(haru.childNodes[i]); } } jalutaPuu(document.body);

6.9. Funktsioonide atribuudid Funktsioonidel on olemas ka mõningad „sisse-ehitatud“ atribuudid ja meetodid, mis päritakse Function.prototype prototüübilt. 6.9.1. length Funktsiooni atribuut length väljastab funktsiooni deklaratsioonis määratud sisendparameetrite arvu. Näiteks saab sellega kontrollida, kas funktsiooni käivitamisel on sisestatud kõik vajalikud parameetrid või mitte. function a(b,c,d){ if(arguments.callee.length != arguments.length){ throw new Error("Parameetrite arv ei ole korrektne!"); } return b+c+d; } a(1,2); // veateade a(1,2,3); // 6

6.9.2. prototype Atribuut prototype viitab eeldefineeritud nn. prototüübiobjektile, mis hakkab rolli mängima juhul, kui funktsiooni kasutatakse konstruktorina koos operaatoriga new. Sellisel juhul pärib konstruktoriga loodav objekt funktsiooni prototüübiobjekti, saades seda kasutada viite this abil. 37 / 109


JavaScript, Andris Reinman

Lähemalt saab prototüüpide kohta lugeda Objektide peatükist. 6.9.3. call Funktsiooni meetod call käivitab funktsiooni koos meetodiga etteantud parameetritega ning objektiviidaga this. Meetodi skoop muudetakse objektiviidaga orginaalsest asukohast etteantud objekti juurde. var part = { hääl: "prääks", prääksu: function(kordadeArv){ for(var i=0; i<kordadeArv; i++){ alert(this.hääl); } } } var lehm = { hääl: "ammuuu" }; part.prääksu(3); // kolm korda teade "prääks" part.prääksu.call(lehm, 3); // kolm korda teade "ammuu", objektiviidaks on objekt lehm

Objekti part meetod prääksu väljastab kolm korda objekti lehm väärtuse hääl, kuigi objektil lehm endal vastav funktsioon üldse puudub. 6.9.4. apply apply on praktiliselt sama meetod, mis call, ainult et parameetrite ükshaaval esitamise asemel võetakse sisendiks ühtne massiiv, mille elemendid edastatakse vastavalt kutsutava meetodi parameetritena. function a(b,c,d){ // funktsiooni sisu } var massiiv = [1,2,3]; a.apply(null, massiiv);

38 / 109


JavaScript, Andris Reinman

7. Globaalsed objektid Globaalsed väärtused, funktsioonid ja objektid on defineeritud JavaScripti poolt ning on kättesaadavad läbi terve programmi, olles seega kasutatavast koodist sõltumatud. Globaalsed objektid kuuluvad reeglina window objekti juurde, olles window meetoditeks ja omadusteks, kuid nende kasutamisel võib eesliite window. koodi kirjutamisel ära jätta. var d1 = new window.Date(); var d2 = new Date();

Mõlemad read teevad sama asja - luuakse uus ajaobjekt. Ühel juhul aga on ära märgitud, et Date pärineb window objektist, teisel juhul on see ära jäetud. Lisaks JavaScripti poolt defineerituile kuuluvad ka kõik kasutaja loodud globaalsed objektid (näiteks muutujad, mis pole defineeritud märksõnaga var) tegelikult window objekti juurde. Seda teades on võimalik ühes koodis kasutada nii lokaalset kui ka globaalset sama nimega muutujat. a = 1; (function z(){ var a = 2; alert(a); // 2 alert(window.a); // 1 })()

7.1. Globaalsed väärtused Globaalsed väärtused on mitmed eritüübilised väärtused, mida teistmoodi pole võimalik kirja panna (näiteks lõpmatuse väärtus Infinity või mitte-number NaN). Antud väärtused on defineeritud kui window objekti omadused. 7.1.1. Infinity Infinity tähistab lõpmatust. Tagastatakse näiteks nulliga jagamisel. Võib olla nii positiivne, kui negatiivne. Käitub matemaatilise lõpmatusena - iga tehe, kus numbrile liidetakse või numbrit korrutatakse lõpmatusega, tagastab lõpmatuse. Lõpmatusega jagamine annab väärtuseks nulli. 7.1.2. NaN Numbri eritüüp mitte-number NaN ei ole kunagi võrdne ühegi numbriga, sealhulgas iseendaga. NaN tuvastamiseks tuleb kasutada funktsiooni isNaN. Väärtuse NaN tagastab näiteks jagamistehe, mille üheks operandiks on mittenumbriline tekst. NaN == NaN; // false isNaN(NaN); // true

7.1.3. undefined undefined on muutujate esialgseks väärtuseks juhul kui muutuja lähtestamisel jääb väärtus seadmata. Samuti tagastab selle väärtuse funktsioon, millel on tagastusväärtus seadmata.

39 / 109


JavaScript, Andris Reinman var i; //undefined function a(){} a(); // undefined

Kuna undefined on tegelikult globaalse objekti (brauserites on selleks window) omaduseks, on sisuliselt tegemist muutujaga. Omaduse undefined väärtus on programmi alguses primitiivtüüp undefined, kuid programmi täitmise käigus on seda väärtust vajadusel võimalik muuta. Tehetes on undefined loogikaväärtusena võrdne väärtusega false, numbrina NaN ning stringina "undefined".

7.2. Globaalsed funktsioonid Globaalsed funktsioonid on erinevad window objekti meetodid, mis on peamiselt mõeldud erinevate abistavate toimingute läbiviimiseks. Näiteks encodeURIComponent stringide teisendamiseks HTTP päringute sooritamisel või isNaN kontrollimaks numbri kehtivust. 7.2.1. endoceURI String encodeURI(String URI) encodeURI

teisendab ressursiidentifikaatori (URI) teksti, asendades osad märgid (erisümbolid) ühe, kahe või kolme paojadaga, mis tähistavad vastava märgi UTF-8 kodeeringukoodi. Asendatakse kõik märgid, mis ei kuulu järgmiste hulka ladina tähed (a-z), numbrid, ";" , "," , "/", "?", "$", "-", "_", ".", "!", "~", "*", "'", "(", ")"

":",

"@", "&",

"=",

"+",

encodeURI('http://www.neti.ee/cgi-bin/webnews?t=õäöü'); // "http://www.neti.ee/cgi-bin/webnews?t=%C3%B5%C3%A4%C3%B6%C3%BC" // %C3 + %B5 = õ. // %C3 on paojada, kus paomärgiks on % ning jada sisuks 16 süsteemis // number 00..FF, tähistades sellega mingit kindlat baiti. // %C3 + %A4 = ä // %C3 + %B6 = ö // %C3 + %BC = ü

Kuna asendusel eeldatakse, et parameetriks on täielik URI ning jäetakse vahele sümbolid nagu ?, & ja =, ei saa seda funktsiooni kasutada näiteks AJAXi päringus saadetavate parameetrite kodeerimiseks. Selle jaoks tasub vaadata funktsiooni encodeURIComponent. 7.2.2. decodeURI String decodeURI(String URI) decodeURI

on funktsiooni encodeURI pöördfunktsioon. Teisendatud paojadad asendatakse tekstis originaalsete sümbolitega. 7.2.3. encodeURIComponent String encodeURIComponent(String URIComponent) encodeURIComponent

teisendab ressursiidentifikaatori (URI) komponendi, asendades osad märgid (erisümbolid) ühe, kahe või kolme paojadaga, mis tähistavad vastava märgi UTF-8 40 / 109


JavaScript, Andris Reinman

kodeeringukoodi. Kui encodeURI on mõeldud terve URI teisendamiseks, siis encodeURIComponent ootab sisendiks ainul URI komponenti (mõne parameetri väärtust), kaasates teisenduseks sümbolid ?, & ja = ja tehes sellega antud funktsiooni funktsioonist encodeURI tunduvalt kasulikumaks. Nimelt saab seda funktsiooni kasutada näiteks AJAX-i päringutes POST ja GET parameetrite kodeerimiseks. encodeURI

kasutamise korral peame olema kindlad sisendi väärtuse suhtes - tavaliselt aga tahame ju edastada hoopis mingit muutuvat informatsiooni. Näiteks kasutaja kirjutab lahtrisse soovitud teksti ning meie saadame selle AJAX'i päringuga serverile. Kõik on korras kui tekstis pole eelpoolmärgituid sümboleid - juhul kui aga on, tekitab see encodeURI korral kiiresti probleemi. Nimelt on need sümbolid mõeldud väärtuste esitamiseks võtme-väärtuse paaridena tekstikujul url? param1=value1&param2=value2 ning ootamatute sümbolite esinemised võivad selle masinloetava teksti ära rikkuda. Paremal juhul saab server kätte teksti, kust puuduvad osad tähed, halvemal juhul aga kirjutatakse üle mõni oluline parameeter. Kuna encodeURIComponent teisendab aga kõik vajalikud sümbolid vastavate paojadadega, siis sellisel juhul vastavat probleemi ei teki. var ajax_post_body = 'param=' + encodeURIComponent('Siin on mõned erisümbolid, &?=.'); // param=Siin%20on%20m%C3%B5ned%20eris%C3%BCmbolid%2C%20%26%3F%3D

7.2.4. decodeURIComponent String decodeURIComponent(String URIComponent) decodeURIComponent

on funktsiooni encodeURIComponent pöördfunktsioon. Teisendatud paojadad asendatakse tekstis originaalsete sümbolitega. 7.2.5. eval mixed eval(String javascript) eval

käivitab stringi kujul saadud parameetri kui JavaScripti koodi.

eval("alert(1)"); // avaneb teateaken sisuga "1"

Võimaluse korral ära kasutaseda funktsiooni. Funktsiooniga eval kaasneb kaks olulist probleemi. Esiteks käivitub eval funktsioonile antud tekst ühena koodi osast, samas aga kui kuskil peaks tekkima mingi viga, on põhjust raske leida. Vea kohta antav info - näiteks rea number, kus viga tekkis - ei pruugi meile öelda mitte midagi, kuna sellist rida pole reaalselt olemas, see luuakse programmi sisse jooksvalt eval käsu käivitudes. Teiseks on probleeme turvalisusega. Kui funktsioon käivitab skriptina teksti, mis kasutab ebausaldusväärset allikat (näiteks brauseri veebiaadressi riba), võib programm kergesti häkkerite saagiks langeda. Loe lähemalt turvalisuse peatükist. 7.2.6. isFinite Boolean isFinite(mixed number) Kontrollib, kas parameetrina lisatud väärtus on lõplik number. Juhul kui parameetri väärtuseks on NaN, Infinity või -Infinity on tagastusväärtuseks false, vastasel korral true. isFinite(23); // true isFinite(Infinity); //false 41 / 109


JavaScript, Andris Reinman

7.2.7. isNaN Boolean isNaN(mixed väärtus) Kontrollib kas parameetrina lisatud väärtus pole number. Numbrina arvestakse ka stringe mida saab konverteerida numbriks („123“). isNaN("abc"); //true isNaN(23); // false

7.2.8. parseFloat Number parseFloat(mixed väärtus) Arvutuste tegemine muutujatega osutub üsna keeruliseks, kui mõni sisendväärtus on tekstikujuline näiteks pärineb HTML lehel olevast tekstiväljast. Nimelt muudetakse liitmisel mõlemad operandid tekstiks, kui üks seda juba on. Arvude liitmisel me sellist käitumist siiski ei soovi (3 + „3“ == „33“) ning seega oleks vaja tekstikujuline number kõigepealt „päris“ numbriks saada. vastava tegvuse jaoks saabki kasutada funktsiooni parseFLoat. parseFloat

teisendab teksti ujukoma numbriks. Funktsioon töötleb teksti sümboli kaupa vasakult paremale ning töötab seni, kuni saabub teksti lõpp või ilmneb sümbol, mis ei ole +, -, 0-9, komakoha eraldaja . või eksponent E. Lubatud on eelnevad ja järgnevad tühikud. parseFloat("33"); // 33

7.2.9. parseInt Number parseInt(mixed väärtus [, Number radix = 10]) parseInt

teisendab teksti täisarvuks (ei ümarda). Erinevusena funktisoonist parseFloat omab funktsioon parseInt täiendavat valikulist sisendparameetrit radix, mis tähistab teisendatava numbri järgu alust. Juhul kui nimetatud parameeter on määramata, kasutab skript 0x algusega teksti puhul järgu alusena kuueteistkümnendsüsteemi, 0 puhul oktaalsüsteemi. Vaikimisi on järgu aluseks kümnendsüsteem. parseInt("10") // 10, kümnendsüsteem parseInt("010"); // 8, oktaalsüsteem parseInt("0x10"); // 16, kuueteistkümnendsüsteem

7.3. Globaalsed objektid Globaalsed objektid on peamiselt erinevad konstruktorid, mis võimaldavad luua erinevaid - näiteks String või Error tüüpi - objekte. 7.3.1. Array Array new Array(mixed parameetrid) Array objekt võimaldab luua massiive. Täpsemalt saab nende kohta lugeda Massiivide peatükist. Massiiviobjekti saab deklareerida järgnevalt: var massiiv = new Array([parameetrid]);

42 / 109


JavaScript, Andris Reinman

Kui massiiviobjekti loomisel pole parameetreid määratud, luuakse tühi massiiv. Juhul kui massiiviobjekti parameetriks on ainult üks number, käsitletakse seda massiivi suurusena ning luuakse massiviobjekti parameetri väärtuse suurune hulk undefined väärtusega massiivielemente. Kui aga parameeter ei ole number või parameetreid on mitu, saavad massiivi elementide väärtusteks parameetrite väärtused. var massiiv1 = Array(); // [] var massiiv2 = new Array(2); // [undefined, undefined] var massiiv3 = new Array(1,2,3); // [1,2,3]

Massiivi indeksiteks saavad olla vaid numbrid. Proovides lisada massiivile väärtust stringikujulise indeksiga, lisatakse väärtus massiivile objekti omadusena. 7.3.2. Boolean Boolean new Boolean(Boolean väärtus) Boolean objekt on loogikaväärtuse koostamiseks. See on siiski suhteliselt harva kasutatav vorm, kuna new Boolean(väärtus) meetodil loodud väärtus true või false ei ole ühilduvad primitiivsete väärtustega true ja false. Näiteks tingimuslause if(new Boolean(false)){} on oodatust vastupidiselt tõene ning {..} blokis olevad laused lähevad täitmisele. See tuleneb faktist, et primitiivne false ootab väärtuse mitte-olemist. new Boolean konstruktoriga loodud objektil on aga väärtus olemas, isegi kui selleks väärtuseks on false. 7.3.3. Date Date new Date(mixed parameetrid) Date võimaldab luua objekte, mille väärtuseks on erinevad ajad (vaikimisi hetkeaeg). Objekti deklareerimise süntaks on järgmine: var aeg = new Date([parameeter]);

kus parameeter võib olla • seadmata. Sellisel juhul on konstruktori tagastatava objekti väärtuseks hetke aeg. • millisekundid alates esimesest jaanuarist, 1970 (UTC) • tekstikujuline aeg (RFC 822 standardi järgi) • komadega eraldatult numbritega aasta, kuu, päev [, tund, minut, sekund, millisekund]

Erinevate kuupäevadega objektide loomine võimaldab näiteks arvutada kahe kuupäeva vahelist aega. var aeg1 = new Date(); // Tänane päev var aeg2 = new Date(2000,1,1); // Esimene jaanuar, 2000 var vahe = aeg1.getTime() - aeg2.getTime(); // ajavahe millisekundites var paevi = Math.floor(vahe/(1000*3600*24)); // ajavahe päevades alert('Esimesest jaanuarist 2000 on möödas '+paevi+' päeva');

Lähemalt saab Date objekti kohta lugeda kuupäevade peatükist.

43 / 109


JavaScript, Andris Reinman

7.3.4. Error Error new Error([String teade [,String failiNimi [,Number reaNumber]]) Konstruktor Error võimaldab koostada objekte veainfoga, mida saab kasutada koos käsuga throw. var a; try{ if(a === undefined){ throw new Error("Viga! Muutuja a väärtus on seadmata"); } }catch(E){ alert(E.message); }

7.3.5. EvalError EvalError objekt väljastatakse, kui käskluse eval väljakutsumine pole korrektne. Näiteks võib (aga ei pea, oleneb brauserist) viga tekkida, kui funktsioon eval omistatakse mõnele muutujale. var minuEval = eval; // võib tekkida EvalError veaobjekt

7.3.6. Function Function new Function([mixed param1[, mixed param2[…,mixed paramN]]], String funktsiooniSisu)

Iga funktsioon JavaScriptis on tegelikult konstruktori Function objekt. Funktsiooni objekti konstruktoriga Function saab defineerida järgnevalt: var funktsioon = new Function([param1[, param2[...,paramN]]], funktsiooniSisu);

Näiteks var funktsioon = new Function('number','alert(number)'); funktsioon(123); //123

Funktsioonide, sh. funktsiooniobjekti kohta on pikemalt juttu funktsioonide peatükis. 7.3.7. Math Math on JavaScriptis globaalne objekt, mis sisaldab mitmesuguseid staatilisi meetodeid ja omadusi matemaatiliste operatsioonide läbiviimiseks. Erinevalt teistest globaalsetest objektidest, ei kasutata Math objekti konstruktorina. Täpsemalt saab Math objekti kohta lugeda matemaatika peatükist. 7.3.8. Number Number new Number(Number number) Numbriobjekt koostab primitiivse numbritüübi ümber objekti, mis võimaldab numbritele rakendada mitmeid meetodeid ning omadusi. Loe numbriobjektist lähemalt numbrite peatükist. 44 / 109


JavaScript, Andris Reinman

7.3.9. Object Object new Object() Globaalne objekt Object on uute objektide koostamiseks. Alternatiivne variant, oleks objekti defineerimisel kasutada Object konstruktori asemel objektiliteraale {}. var objekt = new Object(); var objekt2 = {};

Loe objektide kohta lähemalt objektide peatükist. 7.3.10.

RangeError RangeError objekt väljastatakse, kui number ei mahu etteantud piiridesse. Näiteks tagastab sellise vea järgmine konstruktsioon: new Array(4294967296);

Näites üritame luua massiivi, mille elementide arvuks on 4294967296, kui maksimaalselt lubatud piiriks 4294967295. 7.3.11.

ReferenceError ReferenceError objekt väljastatakse, kui üritatakse opereerida defineerimata muutujaga. alert(r); // muutuja r on defineerimata

7.3.12. RegExp RegExp new RegExp(String regulaaravaldis, String lipud) RegExp

võimaldab defineerida regulaaravaldist. Alternatiivina saab kasutada ka regulaaravaldise literaale //. var re = new RegExp("[0-9]+","g"); var re2 = /[0-9]+/g;

Lähemalt saab regulaaravaldistest lugeda regulaaravaldiste peatükist. 7.3.13. String String new String(String string) String

objekt ümbritseb stringiprimitiive, võimaldades stringidele rakendada erinevaid meetodeid ja omadusi. Loe lähemalt stringiobjektide kohta stringide peatükist. 7.3.14.

SyntaxError SyntaxError objekt väljastatakse, kui programmikoodis on süntaksiviga. var r = [} // süntaksiviga 45 / 109


JavaScript, Andris Reinman

7.3.15.

TypeError TypeError objekt väljastatakse, kui mingi vajalik väärtus ei ole oodatud tüüpi. function a(number){ if(typeof number != 'number'){ throw new TypeError("Parameeter ei ole number!"); } } a("test"); // tüübiviga, "test" ei ole number

7.3.16. URIError Veaobjekt URIError väljastatakse vigase URI puhul, näiteks funktsioonidega decodeURI ja decodeURIComponent, kui parameetrina edastatud string on vigane. decodeURI("%x2345"); // string on vigane

46 / 109


JavaScript, Andris Reinman

8. Objektid ja objektorienteeritud programmeerimine Mõnikord arvatakse, et JavaScript pole objektorienteeritud keel, kuid paraku on see ekslik ning kaugel tõest - JavaScript koosnebki peamiselt just objektidest ning pakub objektorienteeritud programmeerimiseks piisavalt võimalusi. JavaScripti prototüübipõhine objektorienteeritus võib küll näida paljudele esimese pilguga harjumatu ja võib olla ka arusaamatuna - puuduvad ju näiteks klassid kui sellised (sellest ka ehk eksiarvamus, et JavaScript pole objektorienteeritud), samuti on võib olla harjumatu prototüübiline delegeerimine. Tegelikkuses aga on JavaScripti OO üllatavalt võimekas, suutes pakkuda palju sellist mida oodatagi ei oskaks.

8.1. Omadused ja meetodid Objektid on JavaScriptis erinevad võtme-väärtuse paaride kogumid. Võtit nimetatakse objekti omaduseks ning selle väärtuseks võib olla näiteks lihttüübiline väärtus (number, string, loogikaväärtus) või mõni teine objekt (sh. massiiv või funktsioon). Objekti omaduste juurde pääseb läbi punktnotatsiooni kus punkt eraldab objekti ning selle omadust. objekt.pikkus = 50;

Kui omaduse väärtuseks on funktsioon, nimetatakse seda omadust objekti meetodiks. window.alert(123);

Siin on alert objekti window meetodiks. Teise võimalusena saab objekti käsitleda ka assotsiatiivse massiivina, millisel juhul tuleb punktnotatsiooni operaator . asendada nurksulgudega. Kuna nurksulud võtavad sisendiks erinevalt punktnotatsioonist omaduse enda asemel omaduse nime tekstikujul, saab seega dünaamiliselt (stringi muutes) määrata missugust väärtust küsime. var tyyp = "pikkus"; objekt[tyyp] = 50; alert(objekt[tyyp]); // Väljastab: 50

Objekti omadusi ja meetodeid saab kasutada nagu tavalisi muutujaid. Nad tagastavad mingi määrtuse, neile saab omistada uut väärtust ning neid saab kasutada funktsioonile edastatava parameetrina. Omadusi ja meetodeid saab objektile luua lihtsalt neile väärtust andes. Näiteks kui meil on objekt maja, millele me tahame lisada omadust katus ning omistada sellele mingi väärtuse, saame seda teha järgnevalt: maja.katus = "plekk";

Objektile maja lisatakse omadus katus, mille väärtuseks saab plekk. Sarnaselt saab lisada ka meetodeid. maja.misKatus = function(){ return this.katus; } alert(maja.misKatus()); 47 / 109


JavaScript, Andris Reinman

Kontrollimaks, kas objekt sisaldab mingit omadust või meetodit, saab kasutada operaatorit in. if("misKatus" in maja){ alert(maja.misKatus()); //käivitatakse ainult juhul, kui selline meetod on objektis olemas }

Objekti kõikide omaduste ja meetodite loetlemiseks, saab kasutada struktuuri for in. Struktuur väljastab ükshaaval kõik objektis olevate omaduste ja meetodite nimetused. Kusjuures järjestus on suhteliselt juhuslik - lisatud omadused paiknevad objektis nii nagu konkreetses arvutis on parasjagu vaba mälukohti olnud. Reeglina tulevad omadused küll lisamise järjekorras, aga see järjekord ei ole garanteeritud. for(var i in maja){ alert(i); }

Omaduse ja meetodi kustutamiseks objektist saab kasutada operaatorit delete. delete maja.katus; alert(maja.katus); // undefined

Meeles tuleb pidada, et kustutamisel operaatoriga delete, ei kustutata mälust väärtust ennast, vaid objektis olev viide selle väärtuse juurde.

8.2. Objekti loomine Objekti saab luua kahel viisil. Esiteks saab selle luua läbi oroperaatori new, mis loob operaatorist paremal olevast konstruktorfunktsioonist uue isendi. var objekt = new Object(); var aeg = new Date(); var regulaaravaldis = new RegExp();

Operaator new loob uue tühja objekti ning seejärel käivitab funktsiooni, edastades funktsioonile viite this äsja loodud uue objekti juurde. Konstruktorfunktsioon on mõeldud uue objekti algväärtustamiseks vajalike väärtuste ja tegevustega. Teiseks saab kasutada objektiliteraale, mis kujutavad endast loogelisi sulge. var objekt = {};

Objektiliteraal sisaldab komadega eraldatud võtme-väärtuste paare, kus võti (omadus või meetod) ja väärtus on omakorda eraldatud kooloniga. Omaduste nimed saab literaalis esitata nii nimetusena kui ka stringina ning omaduse väärtuse saab määrata suvalise avaldisega - omaduse väärtuseks saab teostatud avaldise poolt tagastatud väärtus. Objektiliteraale on lubatud ka pesastada, st. et literaalis defineeritud objekti omaduse väärtuseks võib omakorda olla uus objektiliteraal. 48 / 109


JavaScript, Andris Reinman var objekt = { pikkus: 100, laius: 150, nurgad: { "alumine": Math.sin(45)*100, "ylemine": Math.sin(60)*50 } }

Järgmises näites emuleerime operaatori new töö mõistmiseks selle tegevust alternatiivsete meetodite abil. Loome funktsiooni, mis sisendiks saadud konstruktorfunktsiooni põhjal loob uue objekti ning seab selles kõik vajalikud väärtused, sealhulgas prototüübiahela. // funktsioon uus, mis asendab operaatori new function uus(konstruktor){ var uus_objekt = {}; konstruktor.apply(uus_objekt, Array.prototype.slice.call(arguments).slice(1)); uus_objekt.__proto__ = konstruktor.prototype; uus_objekt.constructor = konstruktor; return uus_objekt; } // konstruktorfunktsioon function Objekt(andmed){ this.andmed = andmed; } Objekt.prototype.teata = function(andmed){ alert(this.andmed); } // loome konstruktorfunktsiooniga uue objekti, kasutades operaatori new asemel funktsiooni uus var objekt = uus(Objekt,"sisu"); objekt.teata(); // "sisu"

Näites emuleerib funktsioon uus operaatori new tegevust. Funktsioon saab parameetriks konstruktorfunktsiooni ning sellele edastatavad parameetrid. Esiteks loob funktsioon lokaalsesse skoopi tühja uue objekti objektiliteraali abil var uus_objekt = {};

millest saabki funktsiooni täitmise lõpus tagastatav objekt. Seejärel käivitame konstruktorfunktsiooni, määrates funktsiooni meetodiga apply objektiviiteks loodud objekti ning parameetriteks kõik funktsioonile uus edastatud parameetrid. konstruktor.apply(uus_objekt, Array.prototype.slice.call(arguments).slice(1));

Kuna esimene parameeter on konstruktorfunktsioon ise, tuleb see argumentide nimekirjast eemaldada. Kuna aga arguments parameeter pole massiiv vaid massiivilaadne objekt, puuduvad selles operatsiooni läbiviimiseks vajalikud meetodid. Seega tuleb tuleb arguments kõigepealt massiiviks teisendada, mida saame teha läbi Array objekti meetodi slice. 49 / 109


JavaScript, Andris Reinman

Järgmiseks määrame ära loodud objekti prototype viite, milleks saab konstruktorfunktsiooni prototype objekt. Kasutame selleks objekti peidetud omadust __proto__. uus_objekt.__proto__ = konstruktor.prototype;

Ja viimase sammuna märgime ära objekti konstruktori, milleks saab kasutataud konstruktorfunktsioon. uus_objekt.constructor = konstruktor;

Edasi ei jää muud, kui loodud objekt tagastada väljastuskohta, kus seda saab kasutada täpselt samamoodi, kui operaatoriga new samast konstruktorfunktsioonist loodud objekte.

8.3. Objektide kettimine Juhul kui objekti erinevate meetodite tagastusväärtuseks on viide this või mõni muu objekt, saab neid meetodeid vajadusel mugavalt üheks pikaks lauseks kokku kettida. var objekt = { esimene: function(nr){ alert(1*nr); return this; }, teine: function(nr){ alert(2*nr); return this; }, kolmas: function(nr){ alert(3*nr); return this; } } objekt.esimene(3).teine(3).kolmas(3); // 3, 6, 9

Kasulik on see näiteks juhul, kui on tarvis seada korraga objekti erinevaid väärtusi. Samuti kasutavad antud võimalust laialdaselt erinevad JavaScripti raamistikud, näiteks Prototype ja jQuery - teoreetiliselt on jQuery raamistikku kasutades võimalik kirjutadagi ainult ühe lausega terve JavaScripti programm. Loetavusele võib antud lähenemine mõjuda muidugi ekstreemsematel juhtudel üsnagi laastavalt, seega tasub objektide kettimist kasutada pigem konservatiivselt.

8.4. this this

pseudomuutuja viitab hetkel aktiivsele objektile. Tegu on alternatiiviga objekti enda nimele, võimaldades funktsioonil saata teateid objektile, mille meetodiks ta ise on. Näiteks konstruktorit defineerides ei pea seega teadma lõpliku objekti nime, mis konstruktori abil luuakse. Funktsioonides on this seotud ühega järgnevatest: • Objektiga, millega funktsioon on seotud kui tegu on konstruktorfunktsiooni või objekti meetodiga • Meetoditega call või apply funktsioonile edastatud objektiga • Kõikidel muudel juhtudel globaalse objektiga (brauserites on selleks window), sh. näiteks 50 / 109


JavaScript, Andris Reinman

anonüümsetes funktsioonides, mis on defineeritud konstruktorfunktsioonide ning objektide meetodite skoobis function Konstruktor(){ this.a = 1; function b(){ this.a = 2; } b(); alert(this.a); // 1 } new Konstruktor(); alert(a); // 2

Eelnevas näites on lause this.a = 1; korral this seotud konstruktorfunktsiooni loodud objektiga, funktsioonis b oleva rea this.a = 2; puhul aga on this seotud globaalse objektiga window. Kuna globaalse objekti puhul ei ole vaja muutujat this ega window eraldi märkida, saabki muutuja a väärtuse lugemiseks kasutada otsepöördumist real alert(a). Sisuliselt on programmi skoop lahendatud järgmiselt with(window){ // JavaScripti programm }

Seega ongi võimalik kasutada näiteks this.alert() või window.alert() (globaalses skoobis this === window) asemel lihtsalt funktsiooni nimetust alert(). Kuna funktsioonide skoobis defineeritud funktsioonides on this seotud globaalse objekti külge, on reeglina vaja kuidagi viidet originaalse objekti juurde. Selleks on võimalik kasutada sulundis kehtivad lokaalset muutujat. Viite saamiseks omistame this konstruktorfunktsioonis või objekti meetodis lokaalsele muutujale ning skoobis defineeritud sulundfunktsioon saab seda muutujat kasutada soovitud objekti viidana. function Konstruktor(){ this.a = 1; var that = this; function b(){ that.a = 2; } b(); alert(this.a); // 2 } new Konstruktor(); alert(a); // undefined, muutuja a on defineerimata

8.5. Konstruktorfunktsioonid Konstruktorfunktsioonide nimetused esitatakse reeglina suure algustähega. Tegu ei ole keelelise süntaksiga, mis eiramisel annab veateate, vaid võttega koodi loetavamaks tegemisel. Näiteks aitab see vältida vigu, kus konstruktorfunktsiooni kasutatakse ilma operaatorita new. Programm töötab sellisel juhul tõrgeteta (konstruktorfunktsioon on siiski lihtsalt üks eritüübiline funktsioon, mida saab ka niisama käivitada), ainult et tõenäoliselt ei tee programm seda, milleks ta plaanitud on. 51 / 109


JavaScript, Andris Reinman var Konstruktor = function(andmed){ this.andmed = andmed; }

Kui me nüüd kasutame konstruktorfunktsiooni Konstruktor koos operaatoriga new, loome sellega uue objekti, mille argumendi andmed väärtuseks saab objekti loomisel funktsioonile antud parameetri väärtus. var objekt = new Konstruktor(123); alert(objekt.andmed); // 123

Kui me teeme sama ilma operaatorita new, saame oodatult veateate. var objekt = Konstruktor(123); alert(objekt.andmed);

Kuid veateade ei tule esimeselt realt var objekt = Konstruktor(123); - seal on kõik korrektne, konstruktorfunktsioon käivitatakse lihtsalt tavalise funktsioonina. Veateate annab hoopis teine rida alert(objekt.andmed);. Nimelt tagastab funktsioon alati mingi väärtuse. Juhul kui funktsiooni on kasutatud konstruktorina koos operaatoriga new on tagastusväärtuseks viide funktsiooni loodud isendi juurde - this. Kui funktsiooni on kasutatud ilma operaatorita new ning funktsioonis puudub väärtust tagastav lause return, on tagastusväärtuseks eriväärtus undefined. Seega muutuja objekt väärtuseks saab esimesel real undefined ning kui me järgmisel real üritame lugeda objekti omaduse andmed väärtust, saamegi veateate. Eriväärtus undefined ei ole käsitletav objektina ja seega ei saa sellel olla ka omadusi ega meetodeid. Aga mis juhtub funktsiooni deklaratsioonis oleva lausega this.andmed = andmed;? Milline viide this on sel puhul kasutuses - eelnevalt selgus, et operatoorit new kasutamata viidet this funktsiooni isendi juurde ei looda. undefined väärtuse korral aga annab interpretaator omadustega opereerimisel veateate. Juhul kui funktsioonil puudub viide this enese objekti juurde, viitab this globaalse skoobi objektile. Brauseri puhul on selleks globaalse skoobi objektiks window. Seega järgnev lausejada koos window objektiga, on täiesti korrektne ja töötav. var objekt = Konstruktor(123); alert(window.andmed); // 123

Seda, kas funktsioon on hetkel käivitatud tavalise funktsiooni või konstruktorina, saab kontrollida järgnevalt function x(y){ if (this.constructor == x) alert('käivitatud konstruktorina'); else alert('käivitatud funktsioonina'); }

või function x(){ 52 / 109


JavaScript, Andris Reinman if ((this instanceof arguments.callee)) { alert("käivitatud konstruktorina"); } else { alert("käivitatud funktsioonina"); } }

Konstruktorfunktsioon saab olla ka anonüümne. Sellisel juhul tuleb funktsioon deklareerida koos operaatoriga new. Kuna operaator new ootab operandiks funktsiooni, ei ole vahet, kas selleks on mõni nimeline funktsioon või anonüümse funktsiooni deklaratsioon. Sellist anonüümset konstruktorit tasub kasutada juhul, kui soovime luua vaid ühte objekti, mis aga algväärtustamisel peaks sooritama mingeid kindlaid tegevusi. var flash = new function(){ this.installed = false; this.version = -1; //... kontrolli kas flash on brauseris toetatud //... ja leia üles flashi versiooni number } if(flash.installed){ //... lisa lehele flash objekt }else{ document.write('Kahjuks sinu brauser ei toeta Flashi'); }

Näites tuvastame Flash mooduli toe brauseris ning omistame sellega seotud väärtused loodavale objektile flash. Kui edaspidi on lehel vaja Flashi olemasolu kontrollida, on vastav informatsioon juba objektis flash olemas.

8.6. Prototüübid ja delegeerimine JavaScript erineb teistest objektorienteeritud programmeerimiskeeltest peamiselt klasside ning seega ka klassidevahelise pärimise puudumisega - kuigi keeles on olemas reserveeritud nimetus class, pole JavaScript mitte harjumuspäraselt klassipõhine programmeerimiskeel, vaid hoopis prototüübipõhine. Prototüübipõhistes keeltes on klassilaadseid struktuure võimalik emuleerida (vastupidine on tunduvalt keerulisem, kui mitte võimatu), kuid see tähendab täiendava vahekihi loomist, mis alati pole võibolla otstarbekas. Kui klassipõhises keeles defineeritakse esiteks klass ning klassi põhjal luuakse objektid, mis erinevad vaid omaduste väärtuste poolest (olles sisuliselt üksteise identsed koopiad), siis prototüübipõhises keeles tuletatakse objektid teistest objektidest, niiöelda prototüüpidest. Igale objektile eraldi on võimalik määrata tema poolt kasutatavad omadused ja meetodid ning ühisest prototüübist tuletatud objektid võivad üksteisest üsna palju erineda. Huvitaval kombel on JavaScript koos teiste ECMAScript dialektidega sisuliselt ainsad laiemas kasutuses olevad prototüübipõhised keeled. Enamus teisi sarnaseid keeli on kas praktiliselt välja surnud (NewtonScript), või pole nad arendusest kaugemale jõudnudki (Kevo). JavaScripti üht suurimat mõjutajat, programmeerimiskeelt Self arendatakse endiselt edasi, kuid laialdast kasutust pole see senini leidnud. 8.6.1. Objektide kopeerimine JavaScriptis puudub operatsioon objektide otseseks tuletamiseks teistest objektidest, seega võib tinglikult öelda, et JavaScripti puhul pole tegu ka päris ehtsa prototüübipõhise keelega. Selle asemel on keeles operaator new, mis loob uue objekti new ƒ() ning delegeerib loodava objekti omadused ja 53 / 109


JavaScript, Andris Reinman

meetodid konstruktorfunktsiooni prototüüpobjektile ƒ.prototype. Sellise disainiga on üritatud veidigi läheneda klassipõhisele keelele, esitades prototype objekti kui omamoodi klassi, mille alusel saab luua uusi klassi isendeid. Paraku on sellega tekitatud ainult segadust, juhtides tähelepanu eemale JavaScripti tõelisest prototüübipõhisest olemusest. 8.6.2. copy Õnneks on JavaScript väga paindlik ning üsna lihtsalt saab puuduvad operatsioonid asendada. Näiteks keele ühe esivanema, programmeerimiskeele Self laadse operatsiooni copy saab realiseerida järgmise funktsiooniga function copy(object) { function F() {} F.prototype = object; return new F(); }

Sellise funktsiooni abil saab iga objekt olla teise objekti prototüübiks, mis on üks prototüübipõhise objektorienteeritud keele aluseid. Funktsioon võtab sisendiks objekti ning väljastab objekti koopia. Koopia saamiseks luuakse uus konstruktorfunktsioon ning omistatakse selle prototüüpobjektiks F.prototype funktsiooni sisendobjekt object. Kui nüüd konstruktorist luua operaatoriga new uus objekt, mis tagastatakse funktsiooni tagastusväärtusena, saab loodud objekt enda käsutusse kõik konstruktori prototüüpobjekti ehk siis funktsiooni sisendobjekti object omadused ja meetodid. Kopeeritud objektide puhul saame muuta objekti omadusi ja meetodeid, ilma et need muudaksid originaalse objekti andmeid. var a = {val: 123}; var b = copy(a); b.val++; alert(a.val); alert(b.val);

Omistamisoperaatoriga = objekte kopeerida pole võimalik, kuna omistamisel kopeerib JavaScript vaid primitiivseid andmetüüpe (number, loogikamuutuja, string). Objektide puhul omistatakse muutujale väärtuse asemel viit originaalse objekti juurde. Juhul kui eelmises näites oleks teisel real hoopis lause var b = a;, oleks mõlema alert funktsiooni väljund sama - 124. Kuna muutes objekti b, mis on viidaks objekti a juurde, muudame ka objekti a. 8.6.3. __proto__ Lisaks eelpool defineeritud funktsioonile copy on JavaScriptis võimalik objekte tuletada, muutes objektis olevat peidetud omadust __proto__. Antud omadus kujutab endast otsest viidet prototüüpobjekti juurde ning seda seades, saame määrata, millisele objektile antud objekt enda jaoks tundmatud pöördumised delegeerib. var a = {omadus: 123}; var b = {}; b.__proto__ = a; alert(b.omadus); // 123

Kahjuks JScriptis (Microsofti brauseris Internet Explorer JavaScripti asemel kasutatav ECMAScripti dialekt) pole manipuleerimine peidetud omadusega __proto__ võimalik. Seega reaalelulistes rakendustes seda vormi kahjuks kasutada ei saa. 54 / 109


JavaScript, Andris Reinman

8.6.4. Prototüüpobjekt Juhul kui objektil puudub mingi omadus või meetod - puudub seos objekti ja identifikaatori vahel, otsitakse identifikaatorit konstruktorfunktsiooni prototüüpobjektist. Prototüüpobjektis on objekti viit this seotud esialgse päringu saanud objekti juurde. function Ring(){}; f.prototype.PI = 3.14; var ring = new Ring(); alert(ring.PI); //3.14

Objektil ring puudub omadus PI, seega delegeeritakse päring edasi prototüüpobjektile. Juhul kui ka seal vastav omadus puudub, delegeeritaks päring edasi Function.prototype objektile ning sealt Object.prototype objektile. Kui omadust ei ole tervest delegeerimisahelast leitud, tagastatakse väärtusena undefined. Kui loodud objekt implementeerib ise mõne prototüüpobjektis oleva meetodi või kirjutab üle mõne omaduse, jääb prototüüpobjektis väärtus muutmata, jäädes edaspidi peidetuks. Väärtus on endiselt olemas, aga läbi loodud objekti sellele enam ligi pääseda ei saa. Samas kõik teised objektid, mis on loodud sama konstruktorfunktsiooni kaudu ning pole meetodit või omadust üle kirjutanud, saavad seda endiselt edasi kasutada. Konstruktorfunktsiooni defineerimisel tuleks seega objektide ühised meetodid ning omadused siduda konstruktorfunktsiooni prototüüpobjektiga, mitte defineerida need konstruktorfunktsiooni sisemiselt näiteks sulunditena. Sulundfunktsiooni function Konstruktor(){ this.teade = function(tekst){ alert(tekst); } }

asemel tuleks kasutada prototüüpobjekti function Konstruktor(){} Konstruktor.prototype.teade = function(tekst){ alert(tekst); }

Mõlemad variandid on programmi toimimise seisukohalt võrdsed, kuid sulundi puhul delegeerimise asemel kopeeritakse meetod teade igale konstruktorist tuletatud objektile. Kui meetod on aga seotud konstruktori prototüüpobjekti külge, meetodi pärimised objektilt delegeeritakse ühele ja samale prototüüpobjektile. Sellisel lähenemisel on peamiselt kaks positiivset külge, esiteks hoitakse kokku mälu (omaduse või meetodi mitme realisatsiooni asemel tuleb mälus hoida vaid üht) ning teiseks on võimalik hiljem kõikide objektide käitumist korraga muuta. Kui defineerida ümber prototüüpobjektis olev meetod või omadus, muudab see automaatselt kõikide sellest prototüübist tuletatud objektide käitumist, kes pole vastavat meetodit või omadust üle kirjutanud. Sulundi korral tuleks aga sarnase tulemuse saavutamiseks muuta kõiki objekte ükshavaal.

55 / 109


JavaScript, Andris Reinman

8.6.5. Delegeerimine Delegeerimine on mehhanism andmete (objekti omadused) ning käitumise (objekti meetodid) jagamiseks, mis võimaldab kinnistada objekti teate teeninduse teisele objektile. See tähendab, et kui objektilt üritatatakse pärida mingit omadust või üritatakse rakendada meetodit, mis objektis puudub, delegeeritakse päring (objekti viit this jääb seotudks esialgse objektiga) objekti prototüübile, kes siis vastab päringule ise. Kuna prototüüpobjekt on tõenäoliselt tuletatud mingist kolmandast prototüübist, edastab see vajadusel päringu edasi järgmise taseme prototüübile. Kui selliselt moodustunud ahelast päritut ei leita, saadetakse esialgsesse väljakutsekohta tagasi eriväärtus undefined. 8.6.6. Laiendamine JavaScriptis on võimalik laiendada kõiki objekte, lisades või üle kirjutades objektide prototüüpobjektide meetodeid ja omadusi. Konstruktor.prototype.meetod = function([params]){ //this }

Näiteks võime lisada kõikidele objektidele meetodi, mis väljastab ükshaaval objekti kõik loendatavad omadused ja meetodid. Object.prototype.elemendid = function(){ var tulem = []; for(var i in this){ tulem.push(i); } alert(tulem.join(', ')); } var objekt = { number: 123, tekst: "see on tekst" } objekt.omadused(); // number, tekst, elemendid

Nagu näha, muutub ka meetod elemendid üheks loendatavaks elemendiks, seega tasub ettevaatlik olla JavaScripti põhiobjektidele (Object, Array, String jms) uute meetodite lisamisega. Kui mingi osa programmist sõltub lausestruktuurist for..in, võib see tekitada ootamatuid tulemusi.

8.7. Avalikud ja privaatsed omadused ning meetodid JavaScriptis pole eraldi võtmesõna objektides privaatsete omaduste ning meetodite defineerimiseks. Peitmisefekti on võimalik siiski saavutada - kasutades sulundeid. Kui defineerime meetodis või konstruktorfunktsioonis lokaalse muutuja, saavad selle muutuja väärtust lugeda ning seada teised antud funktsiooni skoobis defineeritud meetodid. Konstruktor = function(){ var kaitstud = 0; this.teade = function(){ alert(kaitstud++); } 56 / 109


JavaScript, Andris Reinman } var objekt = new Konstruktor(); objekt.teade(); // 0 objekt.teade(); // 1 objekt.teade(); // 2

Näites objekti meetod teade saab opereerida muutujaga kaitstud, kuid väljastpoolt objekti ja isegi seda meetodit, muutujale kaitstud mingitpidi ligi ei pääse. Meetodit teade nimetatakse privilegeeritud meetodiks, kuna pääseb privaatsele muutujale ligi. Sarnaselt eelnevaga on võimalik defineerida ka privaatseid meetodeid. Konstruktor = function(){ this.a = 0; var that = this; var kaitstudMeetod = function(){ alert(that.a++); }; kaitstudMeetod(); // 0 kaitstudMeetod(); // 1 }

Meetod on ligipääsetav ainult konkreetses skoobis.

8.8. Objektide meetodid Kõik objektid saavad konstruktorina kasutatavalt globaalselt objektilt Object kaasa mitmeid „sisseehitatud“ meetodeid objekti väärtusega opereerimiseks. Erinevad konstruktorid võivad osa neist meetoditest küll vajadusel üle kirjutada (näiteks toString meetod on iga konstruktori korral tihti erinev), kuid vaikimisi on nad igal JavaScripti objektil, hoolimata kasutatavast konstruktorist, alati olemas. 8.8.1. constructor Object object.constructor Omadus constructor viitab konstruktorfunktsioonile, mille abil objekt on loodud. Seda omadust kontrollib näiteks operaator instanceof oma toimingute läbiviimisel. var objekt = new Date(); objekt instanceof Date; //true objekt.constructor === Date; //true

8.8.2. toString String object.toString() toString meetod üritab teisendada objekti tekstikujule. Vaikimis on selleks midagi kujul [object Object], kuid erinevad objektid võivad selle meetodi üle kirjutada. Näiteks Date objekti meetod toString() tagastab hetke aja stringi kujul. var aeg = new Date(); alert(aeg.toString());

Tulemuseks on 57 / 109


JavaScript, Andris Reinman "Sat May 09 2009 12:44:28 GMT+0300 (EEST)"

Vajalik on meetod juhtudel, kui objekti üritatakse kasutada stringi kontekstis, näiteks kasvõi funktsiooni alert parameetrina, milleks oodataksegi stringi. Eelneva näite saab lühemalt kirja panna seega nii: alert(new Date());

8.8.3. toLocaleString String object.toLocaleString() Meetod toLocaleString on mõeldud esitamaks toString meetodi väljundit arvestades kasutaja hetke lokaali. Konstruktoriga Object loodud objektide korral on see sama, mis toString meetodilgi, kui näiteks Number ja Date objektide puhul on lokaaliga juba arvestatud. 8.8.4. valueOf Number object.valueOf() Meetod sarnaneb toString meetodile, kuid erinevusega, et toString kutsutakse välja, kui on vaja objekt teisendada tekstikujule, siis valueOf meetod kutsutakse välja, kui objekti on vaja kasutada näiteks numbrilises kontekstis. Kui Object objektide korral ei tee see meetod suurt midag, siis näiteks Date objektides on tagastusväärtuseks objektis määratud aeg numbrilise ajatempli kujul (millisekundid alates esimesest jaanuarist 1970). 8.8.5. hasOwnProperty Boolean object.hasOwnProperty(String nimi) hasOwnProperty

kontrollib meetodi või omaduse suhet objektiga. Juhul kui meetod või objekt on defineeritud konkreetses objektis, on tagastusväärtus tõene, kui see on aga saadud mõnelt teiselt objektilt prototype ahela kaudu või seda ei eksisteeri üldse, on tagastusväärtus väär. var a = {tekst: "see on tekst"}; a.hasOwnProperty("tekst"); // tõene a.hasOwnProperty("valueOf"); // väär

8.8.6. propertyIsEnumerable Boolean object.propertyIsEnumerable(String nimi) Meetod tagastab tõese väärtuse, kui parameetrina kontrolliks antud meetodi või objekti nimetus stringi kujul on defineeritud kontrollitavas objektis ning see on loendatav - kaastakse for..in tsüklisse. Kuna kõik kasutaja defineeritud meetodid ja omadused on alati loendatavad (see on ka üks põhjus, miks Object.prototype objekti ei ole soovitatav ise üle kirjutada) ning mitteloendatavad elemendid tulevad objektini prototype ahelat pidi ehk need on defineeritud kuskil mujal, on meetodi tagastusväärtus reeglina alati sama mis hasOwnProperty korral. 8.8.7. isPrototypeOf Boolean Object.isPrototypeOf(Object objekt) isPrototypeOf

meetod kontrollib, kas objekt on parameetrina saadud objekti prototüübiahelas. 58 / 109


JavaScript, Andris Reinman var objekt = {}; Object.isPrototypeOf(objekt); //false Object.prototype.isPrototypeOf(objekt); //true Function.prototype.isPrototypeOf(objekt); //true objekt.constructor.prototype.isPrototypeOf(objekt); //true

59 / 109


JavaScript, Andris Reinman

9. Numbrid Konstruktor Number on mõeldud numbriprimitiivide ümber täiendavate meetodite ja omadustega objektide loomiseks. Juhul kui kasutada konstruktorit Number koos operaatoriga new, on tagastusväärtuseks uus Number tüüpi objekt. Ilma operaatorita new saab konstruktorit kasutada tüübi teisenduseks - sisendiks saadud väärtus teisendatakse primitiivsele numbrilisele kujule. var nr1 = new Number(123); // numbriobjekt var nr2 = Number("26"); // 26 var nr3 = Number("ZZZ"); // NaN

Üldiselt ei ole numbrikonstruktori kasutamine reeglina mõistlik. Konstruktori kasutamine lisab koodile omajagu keerukust, samas kui JavaScript konverteerib primitiivsed numbriväärtused vajadusel automaatselt ise numbriobjektiks. Seega kõike, mida saab teha läbi konstruktori genereeritud numbriobjektiga, saab teha ka primitiivse numbriväärtusega.

9.1. Numbrite esitamine Numbriliteraaliks on reeglina ilma täiendava märgistuseta number ise. Komakohad eraldatakse numbris punktiga, kusjuures numbri ja komakoha eraldaja vahele ei tohi jääda muid sümboleid nagu tühikuid. Vastasel korral eeldab interpretaator et punkti puhul on tegu mitte komakoha eraldaja, vaid notatsioonioperaatoriga. Juhul kui komakoha eraldaja ees on vaid number 0, võib selle ka ära jätta. Numbriliteraale saab esitada mitmel viisil. Esiteks kõige lihtsam vorm, kus numbrid tähistavad kümnendsüsteemi numbrit vastavalt kasutatud kujule. 12345.67;

Teiseks oktaalnumbrid (kaheksandiksüsteem, 0..8), mida eristab kümnendsüsteemi numbritest numbri ees käiv number 0. 0777; // 511

Kolmandaks kuueteistkümnendsüsteemi numbrid (0..F), mida saab moodustada, lisades numbri ette märgistuse 0x. 0xFF; // 255

Samuti saab kasutada numbri eksponentkuju, liites mantissile märgistuse E+/- ning selle järel kümne astme. 1.23e3; 1.23e-2; 0.0123

Numbri kuju ei mängi keeles siiski erilist rolli, oluline on väärtus ise, mitte selle esitusviis. Seega on kümnendkujul number ja sama väärtusega oktaalnumber, näiteks 511 ja 0777 üksteisega täielikult võrdsed. 60 / 109


JavaScript, Andris Reinman 511 === 0777; // true

9.2. Omadused Globaalsel objektil Number on mitmed staatilised omadused, mis tähistavad numbriobjekti erinevaid parameetreid, näiteks suurimat kasutatavat numbrit. Staatiline omadus tähendab, et see on defineeritud objektis Number mitte selle prototüübis ning seega ei liigu edasi ka järgnevatele numbriobjektidele. Sellist staatilist omadust saab lugeda kujul Number.MAX_VALUE. Kui proovida sama mõne numbriobjektiga - numbriline_vaartus.MAX_VALUE, on väärtuseks undefined. 9.2.1. MAX_VALUE Number Number.MAX_VALUE Omadus tähistab suurimat kasutatavat numbrit, milleks on umbkaudu 1.79×10308 - kõiki sellest numbrist suuremaid väärtusi tähistab lõpmatuse väärtus Infinity. if(a * b <= Number.MAX_VALUE){ funktsioon1(); }else{ funktsioon2(); }

9.2.2. MIN_VALUE Number Number.MIN_VALUE Omadus tähistab vähimat kasutatavat numbrit, milleks on umbkaudu 5×10-324 - kõiki sellest numbrist väiksemaid väärtusi tähistab 0. if(a / b >= Number.MIN_VALUE){ funktsioon1(); }else{ funktsioon2(); }

9.2.3. NaN NaN Number.NaN Globaalse objekti Number omadus NaN tähistab mitte-numbrilist väärtust ning on võrdne globaalse objekti NaN omaduse väärtusega. NaN väärtust ei saa kasutada võrdlustehetes, kuna ta ei ole millegagi võrdne, sealhugas ka mitte iseendaga. NaN väärtuse kontrollimiseks saab kasutada funktsiooni isNaN. var nr = Number.NaN; nr == NaN; //false isNaN(nr); //true isNaN(Number.NaN); //true

9.2.4. NEGATIVE_INFINITY Number Number.NEGATIVE_INFINITY 61 / 109


JavaScript, Andris Reinman

Numbri omadus NEGATIVE_INFINITY tähistab negatiivset lõpmatust ning on võrdne globaalse objekti omadusega -Infinity. Väärtus tekib, kui positiivne number jagada väärtusega 0 või kui üritada luua suuremat numbrit kui MAX_VALUE. 9.2.5. POSITIVE_INFINITY Number Number.POSITIVE_INFINITY Numbri omadus POSITIVE_INFINITY tähistab lõpmatust ning on võrdne globaalse objekti omadusega -Infinity. Väärtus tekib, kui negatiivne number jagada väärtusega 0 või kui üritada luua suuremat negatiivset numbrit kui -MAX_VALUE.

9.3. Meetodid Numbriobjekti meetodid on rakendatavad kõikidel numbritel - nii numbriobjektidel, kui ka primitiivsetel numbrilistel väärtustel. Viimasel juhul luuakse numbriväärtuse ümber ajutine numbriobjekt ning viiakse meetod läbi selle objekti juures. Peale meetodi töö lõppemist, objekt kustutatakse. Numbriliteraali korral meetodite kasutamiseks tuleb numbri ning punktnotatsiooni operaatori punkti vahele jätta tühik - vastasel korral arvab interpretaator, et tegu on komakoha eraldajaga, mitte punktnotatsiooniga. 1234.toExponential(); //VALE, SyntaxError 1234 .toExponential(); //ÕIGE

9.3.1. toExponential String number.toExponential() Meetod tagastab numbri eksponentesituse stringina Me+-P, kus M on numbri mantiss ning P astendaja. Aluseks on 10, seega numbri täpsem kuju oleks Mx10P. var nr = 134; alert(nr.toExponential()); //1.34e+2

Meetodil on ka valikuline parameeter, mis võimaldab määrata kasutatavate komakohtade arvu eksponentesituse kuvamisel. Vaikimisi näidatakse nii palju komakohti, kui on vaja numbri esitamiseks, kui antud parameetriga saab seda arvu vähendada (ümardatakse). var nr = 123456789; alert(nr.toExponential(2)); //1.23e+8

9.3.2. toFixed String number.toFixed([Number komakohti = 0]) Meetod toFixed tagastab stringi kujul numbri väärtuse, mis on ümardatud parameetris antud (vaikimisi 0) komakoha täpsuseni. 1234.56789 .toFixed(); // "1234" 12e+9 .toFixed(2); // "12000000000.00"

62 / 109


JavaScript, Andris Reinman

9.3.3. toLocaleString String number.toLocaleString() Meetod teisendab numbri stringiks lokaali poolt määratud kujuna. Meetodi tööle ei saa väga kindel olla, kuna arvutites on lokaalid tihtipeale valesti seatud. Samuti käsitlevad erinevad platvormid meetodi tööd erinevalt - halvemal juhul on tulemus täpselt sama mis meetodi toString korral ning lokaali ei võeta arvesse, isegi kui see on korrektselt seatud. 1234567.45 .toLocaleString(); //

"1 234 567,45"

9.3.4. toPrecision String number.toPrecision([Number täpsus]) Meetod toPrecision tagastab numbri väärtuse stringi kujul vastavalt parameetrina saadud nõutud täpsusele. Täpsust hakatakse lugema numbri vasakust servast, kus 1 tähendab, et arvestatakse ainult esimest numbrit ning järgmised asendatakse nullidega. Juhul kui täpsuse parameeter on seadmata, toimib meetod sarnaselt meetodile toString, tagastades numbri väärtuse stringi kujul. 123.56 123.56 123.56 123.56

.toPrecision(1); .toPrecision(2); .toPrecision(3); .toPrecision(4);

//100 //120 //123 //123.5

9.3.5. toString String number.toString([Number radix = 10]) Meetod teisendab numbri stringi kujule. Meetodil on ka valikuline parameeter, millega saab määrata teisendatava numbri baasi (2..36), vaikimisi on selleks 10. 123 .toString(); // "123" 123 .toString(2); // "1111011" 123 .toString(16) // "7B"

9.3.6. valueOf Number number.valueOf() Meetod valueOf tagastab numbriobjekti primitiivse numbriväärtuse. Meetodi kasutamine numbriliteraalil ei ole väga mõistlik - meetod tagastab lihtsalt literaali enda väärtuse, seega omab meetod tähendust vaid numbriobjektide juures. var nr = new Number(123); alert(nr.valueOf()); // 123

63 / 109


JavaScript, Andris Reinman

10.

Stringid

String on JavaScriptis andmetüüp teksti esitamiseks. Stringi (inglise keeles nöör) nimetus tuleb faktist, et stringiväärtuse koostab arvuti mälus üksteise järel olevatest baitidest, millest igaüks tähistab ühte tähte ja mis kokku moodustavadki omamoodi „baitide nööri“. Nagu numbridki, on ka tekst tegelikult objekt, pärides enda omadused Object.prototype prototüübilt. Kõik JavaScripti stringid on unikood kodeeringus, hoolimata HTML lehel kasutataud kodeeringust. Juhul kui HTML leht on mõnes muus kodeeringus, muudab brauser JavaScripti jaoks teksti kodeeringu ära.

10.1.

Stringi loomine

Stringiobjekti saab luua konstruktoriga String. Objekt sisaldab ühe omadusena stringiprimitiivi ning lisaks meetodeid selle stringiga opereerimiseks. Stringiprimitiivi saab luua ka literaalina lihtsalt jutumärke (") või apostroofe (') kasutades, kus nende märkide vahel asuv tekstiväärtus ongi string. JavaScript võimaldab stringiobjekti meetodeid rakendada ka stringiliteraaliga loodud stringidel sellisel juhul loob JavaScript stringiprimitiivi ümber uue ajutise stringiobjekti, käivitab soovitud meetodi, tagastab tulemuse ning kustutab lõpuks ajutise objekti. Sellel põhjusel ei ole ka mõtet väga String konstruktorit kasutada - JavaScript teeb vajaliku töö ise ära. Jutumärkide vahel olev tekst kuulub interpretaatori poolsele töötlemisele (tagurpidi kaldkriipsule järgnevad sümbolid muudetakse nende õigele kujule), aga apostroofidega määratud tekst mitte (v.a. \\ ja \', millest viimane muudetakse tekstiliseks apostroofiks stringi lõpetatuks lugemise asemel). Tagrupidi kaldkriipsuga muudetavad sümbolid on järgnevad • \0 - Erisümbol NUL (\u0000) • \b - Kaldkriips (\u0008) • \t - Tabulatsioonisümbol, horisontaalne (\u0009) • \n - Reavahetus (\u000A) • \v - Tabulatsioonisümbol, horisontaalne (\u000B) • \f - Lehevahetus (\u000C) • \r - Tagasijooks (\u000D) • \" - Jutumärk (\u0022) • \' - Apostroof (\u0027) • \\ - Tagurpidi kaldkriips (\u005C) • \xZZ - Latin-1 kodeeringus sümbol, kahe kuueteistkümnendsüsteemi numbrina • \uZZZZ - UTF-8 kodeeringus sümbol, nelja kuueteistkümnendsüsteemi numbrina Kõik muud sümbolid mis järgnevad tagurpidi kaldkriipsule, jäetakse muutmata. Näiteks \€ on sama mis €. var tekst = new String("Mingi tekst"); var tekst = "Mingi tekst"; 64 / 109


JavaScript, Andris Reinman alert("Esimene rida\nTeine rida");

10.2.

UTF-8

UTF

on akronüüm sõnadest Unicode Transformation Format (Unicode teisendusvorming) ning termini taga olev number kaheksa tähendab kaheksat bitti (oktett). Kodeering on muutpikkusega, kasutades üht kuni nelja oktetti ning on optimeeritud ladina tähtedega märgistike esitamiseks. Esimesed 128 märgistiku positsiooni - milles asuvad ASCII sümbolid - esitatakse muutmatult, jäädes sellega ASCII märgistikuga täielikult ühilduvaks. 10.2.1. Kodeering Erinevalt fikseeritud pikkusega kodeeringutest (näiteks UTF-16) hoiab UTF-8 ruumi kokku, kuna vaikimisi eeldatakse enamuse kasutusel olevaid sümboleid ladina tähtede hulka ning seega kulub sümbolite esitamiseks vaid üks bait UTF-16 kahe baidi vastu. Eesti keeles kasutavad kahte baiti vaid tähed ÕÄÖÜ ning susisevad ŠŽ - kõik teised sümbolid jäävad ühe baidi sisse. Unicode sümbol kodeeritakse n järjestikuse baidina, kus esimese baidi m=n (välja arvatud ühebaidilise sümboli korral, kus m=0) kõrgemat bitti näitavad, mitu baiti on kasutusel, järgmine bitt on null, järgnevate baitide kaks kõrgemat bitti on 1 ja 0. Vabad bitid (tabelis b) kasutatakse sümboli Unicode'i numbri jaoks. Baidid 1

Kasutatavad bitid 7

Esitlusviis

2

11

110bbbbb 10bbbbbb

3

16

4

21

1110bbbb 10bbbbbb 10bbbbbb 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb

0bbbbbbb

Märkus ASCII sümbolid A-Z, 0-9 jms. Diakriitiliste märkidega sümbolid, sh. eesti täpitähed ning kirillitsa Kõik muud sümbolid (v.a. erimärgid) Erimärgid

Tabel 3. UTF-8 baitide kasutamine 10.2.2. BOM Tekstifailide esitamisel Unicode vormingus (UTF-8, UTF-16) peaks tekstiredaktori jaoks olema failis info kasutatava kodeeringu kohta. See saavutatakse läbi faili alguses oleva BOM'i (byte order mark) ehk baidijärjestuse märgiga. Kui tekstiredaktor avab faili ning leiab esimeselt neljalt baidilt BOM-i, oskab ta faili ka vastavalt esitada. UTF-8 BOM näiteks on esitataud kolme baidiga EF BB BF () - juhul kui see on tekstifaili alguses, peaks redaktor käsitlema seda faili UTF-8 vormingus. Probleem BOM-idega kaasneb brauseris veebilehtede esitamisega. Näiteks osad brauserid ootavad veebilehelt esimese märgendina DOCTYPE deklaratsiooni. Juhul kui esimesed sümbolid pole aga mitte <DO vaid , ei hakka brauser dokumenditüübi deklaratsiooni rohkem otsima ning langeb ühilduvusrežiimi vanemate veebilehtedega ühilduvuse tagamiseks. Tulemuseks võib olla veebilehe katkine kujundus - ühilduvus vanemate veebilehtedega tähendab standardite vabakäelisemat kasutamist ning mõningate mittestandardsete praktikate lubamist. Samuti kui BOM on mõne serveripoolse skripti (näiteks PHP) esimeseks märgendiks, ei saa skript reeglina seada HTTP päisesse täiendavaid kirjeid (Content-type: text/plain, Location: ZZZ jne), kuna päiste lisamise hetkeks on skript midagi juba väljastanud (skripti alguses olnud BOM-i), aga päist saab seada ainult enne igasugust väljastust. 65 / 109


JavaScript, Andris Reinman

Seega veebilehtedel UTF-8 kodeeringus teksti esitamiseks tuleks jätta BOM märgend failist üldse ära ning teatada brauserile õige kodeering läbi vastava meta sildi või HTTP päise. Meta

silt kodeeringu määramiseks:

<meta http-equiv="Content-Type" content="text/html; Charset=UTF-8" />

Kirje lisamine HTTP päisesse kodeeringu määramiseks (skriptimiskeeles PHP): Header("Content-Type: text/html; Charset=UTF-8");

HTTP päise muutmine Apache serveris vaikimisi kodeeringu seadmisel (failis .htaccess või serveri konfiguratsioonifailis): AddDefaultCharset utf-8

Lühidalt võib UTF-8 arendaja jaoks kokku võtta nii - tähemärki salvestatakse reeglina kas ühe (ladina tähed) või kahe (täpitähed) baidiga. JavaScripti poole peal ei olegi kodeeringu tuvastamisel väga vahet, kuna brauser hoolitseb ise tekstide ühtse kodeeringu eest. Küll aga peab hoolega jälgima sisendit serveri poolel. Näiteks JavaScriptiga ajaxi pärngut tehes ja encodeURIComponent funktsiooniga teksti serverile arusaadavale kujule viies saab server teksti alati UTF-8 vormingus, isegi kui leht mille ta ise välja saatis, oli Latin 1 (ISO-8859-1).

10.3.

Stringi meetodid

Stringiobjektid saavad String.prototype objektilt kaasa terve hulga kasutatavaid meetodeid, mis aitavad teha mitmesugust tekstitöötlust. Stringide meetodeid saab rakendada nii stringiobjektidele, mis on loodud konstruktoriga String kui ka stringiliteraalidele. Näiteks on täiesti korrektne järgmine lause: alert("mis kell on".substring(5,7)); // kel

Olemas on meetodid nii stringide liitmiseks (concat), regulaaravaldistega teksti kontrollimiseks (match) kui ka pärandmeetodid HTML koodi loomiseks (blink). Kuna veebilehte on tunduvalt mugavam töödelda läbi DOM objektide, siis HTML koodi loomise meetodeid praktiliselt enam ei kasutata. Pealegi ei vasta need ECMAScripti standardile. Ükski stringi meetod ei muuda objekti stringi ennast, seda stringi kasutatakse ainult sisendiks - meetod väljastab tagastuskohta uue, vajadusel muudetud stringi.

10.3.1. charAt String string.charAt(Number indeks) Stringi meetod charAt tagastab stringist märgitud positsioonil asuva sümboli. Positsioonide arvestus algab numbriga 0 ning kui päritav positsioon ei asu vahemikus 0 .. string.length-1, on tagastusväärtuseks tühi string "".

66 / 109


JavaScript, Andris Reinman alert("tere".charAt(0)); alert("tere".charAt(1)); alert("tere".charAt(2)); alert("tere".charAt(3));

// // // //

t e r e

10.3.2. charCodeAt Number string.charCodeAt(Number indeks) Meetod tagastab soovitud positsioonil asuva sümboli unikoodi tähemärgi koodi numbrilise väärtuse, mis jääb vahemikku 0 .. 65535. alert("tere".charCodeAt(1)); // 101 ("e")

10.3.3. concat String string.contact(String parameetrid) Meetod liidab parameetrid (mida võib olla üks või mitu) stringi enda väärtusele ja tagastab niiviisi saadud uue stringi. Stringiobjekti enda väärtus jääb samaks. alert("tere".concat(" ", "maailm")); // tere maailm

10.3.4. fromCharCode String String.fromCharCode(Number parameetrid) fromCharCode

meetod koostab uue stringi parameetrina saadud unikoodi tähetabeli numbrilistest väärtustest. Tegu on staatilise meetodiga, mis tegelikult kuulub konstruktori String juurde. var tekst = String.fromCharCode(116, 101, 114, 101); //tere

10.3.5. indexOf Number string.indexOf(String otsing) Meetod indexOf on mõeldud otsinguks stringis olevast tekstist. Meetod võtab sisendiks otsinguteksti ning valikulise täiendava parameetrina ka positsiooni, millest alates otsingut teostatama hakatakse. Juhul kui otsitav on tekstis olemas, tagastatakse otsitava asukoha algus. Juhul kui midagi ei leita, on tagastusväärtuseks -1. var tekst = "Siin on mingi rida teksti"; alert(tekst.indexOf("in")); // 2 alert(tekst.indexOf("ei ole")); // -1

10.3.6. lastIndexOf Number string.lastIndexOf(String otsing) lastIndexOf otsib sarnaselt meetodiga indexOf tekstist etteantud väärtuse positsiooni, kuid kui meetod indexOf teostab otsingut alustades alguses, siis lastIndexOf teeb sedasama alustades 67 / 109


JavaScript, Andris Reinman

teksti lõpust. var tekst = "Siin on mingi rida teksti"; alert(tekst.indexOf("in")); // 9

10.3.7. length Number string.length Omadus length on kirjutuskaitstud numbriline väärtus, mis sisaldab endas valitud stringis olevate sümbolite arvu. alert("tekst".length); // 5

10.3.8. localeCompare Number string.localCompare(String võrreldav1, String võrreldav2) Meetod võrdleb stringiobjekti parameetriks saadud stringiga ja tagastab positiivse väärtuse, kui parameetrina saadud string on tähestiku järgselt eespool ning negatiivse, kui see paikneb tagapool. Meetod arvestab sümbolite võrdlemisel hetkel aktiivset lokaali. Teoreetiliselt peaks sellisel juhul Eesti arvutites asuma sümbol õ peale sümbolit v, kuid kahjuks ei saa sellele järjestusele kindel olla, kuna arvutitel on harva lokaal korrektselt seatud või pole arvutis Eesti lokaali seadmine võimalikki. var t2hed = ['a','b','c','t','u','v','õ','ä','ö','ü']; t2hed.sort(function(a,b){ return a.localeCompare(b) });

10.3.9. match mixed string.match(RegExp re) match

kontrollib objekti stringi parameetrina saadud regulaaravaldise vastu ning tagastab vaste leidmise korral esimese vaste, kui regulaaravaldises on parameeter g seadmata ning kõik vasted ühise massiivina, kui g on seatud. var tekst = "4 tomatit, 5 kurki"; alert(tekst.match(/[0-9]/g)); // [4,5]

Regulaaravalidste kohta saab täpsemalt lugeda regulaaravaldiste peatükist. 10.3.10. replace String string.replace(RegExp otsing, mixed asendus) Meetod replace asendab objekti stringis sisendina saadud esimese parameetri regulaaravaldisele vastavad kohad teises parameetris oleva väärtusega. Kui regulaaravaldise omadus g on seatud, asendatakse kõik regulaaravaldisele vastavad tekstiosad, vastasel korral asendatakse vaid esimene vaste. Asendatav tekst võib sisaldada mitmeid muutujaid, mis saavad oma väärtuse regulaaravaldiselt. 68 / 109


JavaScript, Andris Reinman Sümbolid $1, $2, …, $99 $& $` $' $$

Asendus tekst mis sisaldus regulaaravaldises 1-99. sulgudes asuvas alamlauses tekst stringis, mis vastas regulaaravaldisele Tekst, mis jääb regulaaravaldisele vastavast tekstiosast vasakule Tekst, mis jääb regulaaravaldisele vastavast tekstiosast paremale Dollarisümbol ($)

var tekst = "3 tomatit ja 67 kurki"; alert(tekst.replace(/([0-9]+)/g,"[$1]"));

Näites lisame kõikidele tekstis esinevatele numbritele ümber kandilised sulud, nii et väljundiks on [3] tomatit ja [67] kurki

Asendajaks võib olla ka funktsioon. Funktsiooni esimene parameeter sisaldab endas kogu regulaaravaldise vastet, teine aga ainult otsitavat (sulgudes olevat). Funktsiooni tagastusväärtus saabki asendajaks. "abcdef".replace(/b(.*?)e/,function(kõik,otsitav){ return "b-" + otsitav + "-e"; }); // ab-cd-ef

Näide asendab stringis b..e funktsiooni poolt tagastatava väärtusega 10.3.11. search Number string.search(RegExp re) search

otsib stringist regulaaravaldisele vastavat teksti ning tagastab sarnaselt meetodile indexOf vaste korral vaste alguse positsiooni. Kui midagi ei leita, on tagastusväärtuseks -1. Erinevalt meetoditest match ja replace ei arvesta search regulaaravaldise omadust g. var tekst = "2 kurki ja 4 tomatit"; alert(tekst.search(/[3-9]/)); // 11

Näites otsime numbrit mis on vahemikus 3 kuni 9. 10.3.12. slice String string.slice(Number algus[, Number lõpp]) Meetod slice väljastab uue stringi, mille sisuks on originaalse teksti osa alates esimese parameetriga märgitud positsioonist teise parameetriga (juhul kui on seatud - vastasel korral kuni stringi lõpuni) märgitud positsioonini. Kui algust tähistav parameeter on negatiivse väärtusega, arvestatakse algust loendades stringi lõpust. "tere maailm".slice(2,5); // "re ma" "tere maailm".slice(-3); // "ilm" 69 / 109


JavaScript, Andris Reinman

10.3.13. split Array string.split(mixed eraldaja[, Number elemente]) Meetod split jagab stringi sisendiks saadud parameetri järgi osadeks ning tagastab need osad ühise massiivina. Parameetriks võib olla nii string kui regulaaravaldis. var tekst = "a|b|c|d|e|f"; tekst.split("|"); // ["a","b","c","d","e","f"] var lause = "turul müüakse tomateid ja kurke"; alert(lause.split(/\s+/).length); // 5

Meetodil on ka teine, valikuline parameeter, mis määrab maksimaalse massiivi elementide arvu juhul kui elementide arv ületab antud parameetris määratud väärtust, lõigatakse ülejäävad elemendid ära. var tekst = "a|b|c|d|e|f"; tekst.split("|", 3); // ["a", "b", "c"]

10.3.14. substr String string.substr(Number algus[, Number pikkus]) substr

tagastab sarnaselt meetodile slice uue stringina valitud osa stringiobjektist. Meetodi esimene parameeter määrab tagastuse alguse positsiooni algses stringis ning teine parameeter määrab tagastatava stringi pikkuse. Juhul kui positsiooni väärtus on negatiivne, hakatakse lugemist arvestama tagurpidi stringi lõpust. Kui pikkuse parameeter on puudu, kaasatakse terve string alates alguse positsioonist. var tekst = "turul müüakse tomateid ja kurke"; alert(tekst.substr(-13, 7)); // "teid ja"

10.3.15. substring String string.substring(Number algus[, Number lõpp]) Meetod substring tagastab sarnaselt meetoditele substr ning slice määratud osa (algus .. lõpp-1) stringist uue stringina. Sisendparameetriteks on alguse postitsioon ning lõpu positsioon, kuid erinevalt meetodist slice, ei saa asukoha märkimiseks kasutada negatiivseid numbreid negatiivne number teisendatakse nulliks. Kui teiseks parameetriks antud number on esimesest väiksem, vahetatakse parameetrite tähendused ära - esimene hakkab tähistama lõppu ja teine algust. var tekst = "abcdefghij"; tekst.substring(2,5); // cde tekst.substring(5); // fghij tekst.substring(5,0); // abcde

70 / 109


JavaScript, Andris Reinman

10.3.16. toLocaleLowerCase String string.toLocaleLowerCase() Teisendab tekstis olevad suurtähed väiketähtedeks arvestades arvutis määratud lokaali. Enamuste keelte puhul on meetodi tulemus täpselt sama, mis meetodil toLowerCase. Erandiks on näiteks Türgi keel, mille tähestikus on olemas ilma täpita i. Sellisel juhul kui muuta suurtähte I (suur i täht) väiketäheks, ei ole tulemus mitte väike i, vaid unikood sümbol ı (\u0131). Eesti keele korral sarnaseid erandeid pole. 10.3.17. toLocaleUpperCase String string.toLocaleUpperCase() Teisendab tekstis olevad väiketähed suurtähtedeks arvestades arvutis määratud lokaali. Nagu meetodi toLocaleLowerCase korral, jääb enamuste keelte puhul meetodi tulemus täpselt samaks, mis meetodil toUpperCase. Kui Türgi lokaali korral muuta väiketähte i suurtäheks, on tulemuseks suure I asemel unikood sümbol İ (\u0130). Eesti keele korral sarnaseid erandeid pole. 10.3.18. toLowerCase String string.toLowerCase() Meetod toLowerCase teisendab kõik stringis olevad suurtähed väiketähtedeks ja tagastab tulemuse uue stringina. var tekst = "Siin On Mõned Suurtähed"; alert(tekst.toLowerCase()); //siin on mõned suurtähed

10.3.19. toString String string.toString() Meetod toString väljastab stringiobjektis oleva primitiivstringi. var tekst = new String("siin on tekst"); alert(tekst.toString()); // siin on tekst

10.3.20. toUpperCase String string.toUpperCase() Meetod toUpperCase teisendab kõik stringis olevad väiketähed suurtähtedeks ja tagastab tulemuse uue stringina. var tekst = "väiketähed"; alert(tekst.toUpperCase()); //VÄIKETÄHED

10.3.21. valueOf String string.valueOf() Meetod väljastab stringiobjektis oleva primitiivstringi. Identne meetodiga toString.

71 / 109


JavaScript, Andris Reinman

10.4.

Mittestandardsed meetodid

JavaScripti versioonis 1.5 puuduvad mõned stringide meetodid, mis võivad tihtipeale siiski kasulikuks osutuda. Üheks selleks võiks näiteks olla trim, mille ülesandeks oleks eemaldada stringi servadest mittevajalikud sümbolid (näiteks tühikud jms.). Järgnevas näites laiendame stringi prototüüpi String.prototype lisades sinna vajalikud meetodid, peale mida on võimalik kasutada deklareeritud meetodeid kõikidel JavaScripti stringidel.

/** * Eemaldab stringis vasakus servas asuvad ettemääratud sümbolid * @param {String} chars Kustutatavad sümbolid (või tühik, kui seadmata) * @return tagastab uue stringi */ String.prototype.ltrim = function(chars){ return this.replace(new RegExp("^["+(chars || "\\s")+"]+", "g"),''); } /** * Eemaldab stringis paremas servas asuvad ettemääratud sümbolid * @param {String} chars Kustutatavad sümbolid (või tühik, kui seadmata) * @return tagastab uue stringi */ String.prototype.rtrim = function(chars){ return this.replace(new RegExp("["+(chars || "\\s")+"]+$", "g"),''); } /** * Eemaldab stringis vasakus ja paremas servas asuvad ettemääratud sümbolid * @param {String} chars Kustutatavad sümbolid (või tühik, kui seadmata) * @return tagastab uue stringi */ String.prototype.trim = function(chars){ return this.replace(new RegExp("^["+(chars || "\\s")+"]+|["+(chars || "\\s") +"]+$", "g"),''); } /** * Muudab tekstis kõikide sõnade esimesed tähed suurtähtedeks * @return tagastab uue stringi suurte algustähtedega */ String.prototype.wordsToUpper = function(){ return this.replace(/\b\w+\b/g, function(word){ return word.substring(0,1).toUpperCase()+word.substring(1); }); }

Näide eespool defineeritud meetodite kasutamiseks: var tekst = "

siin on mingi tekst

alert(tekst.ltrim()); alert(tekst.rtrim()); alert(tekst.trim());

";

// "siin on mingi tekst " // " siin on mingi tekst" // "siin on mingi tekst"

// Eemaldame vasakust servast tühikud, "s" ning "i" tähed 72 / 109


JavaScript, Andris Reinman alert(tekst.ltrim("s i")); // "n on mingi tekst

"

// Muudame s천nade algust채hed suurt채htedeks alert(tekst.wordsToUpper()); // " Siin On Mingi Tekst "

Tasub siiski meeles pidada, et JavaScripti globaalsete objektide prototype objekte ei ole soovitav ise muuta, kuna sellega v천ib kergelt minna konflikti teiste kasutatavate teekidega.

73 / 109


JavaScript, Andris Reinman

11.

Massiivid

Massiivid on andmestruktuurid, mis lubavad andmeid koondada ühise muutuja alla ning teha andmeelementidel vahet järjekorranumbri (indeksi) alusel. JavaScripti massiivid on üpris erinevad teiste keelte massiivitüüpidest. Tegu ei ole mitte omaette andmestruktuuriga, vaid eritüübiliste objektidega, mille peamiseks erinevuseks muudest objektidest on numbrilised indeksid väljade nimedena ning massiivi elementide arvu näitav omadus length. Sisuliselt saab midagi JavaScripti massiivilaadset esitada järgneval kujul, kus objekti väljade nimed on esitatud numbritega. var pseudomassiiv = { "0" : 123, "1" : 456, "2" : 789, "length" : 3 };

Sellist objekti saaks täiesti vabalt kasutada praktiliselt kõikides olukordades, kus eeldatakse sisendiks massiivi. Välja jäävad vaid juhud, kus massiivil peavad olema mõningad massiiviobjektide meetodid, mida eelnenud näites defineeritud pole. Massiivide kirjeldamiseks on olemas ka omaette massiiviliteraal - kandilised sulud [], mille sees eraldatakse erinevad massiivi elemendid komaga. Massiivi elementide indeksid algavad nulliga ning igal järgneval elemendil on indeksi väärtus eelmise väärtusest ühe võrra suurem. Massiivi elemendid ei pea, erinevalt paljudest teistest keeltest, olema sama tüüpi. Korraga võivad massiivi elementideks olla nii primitiivsed tüübid nagu numbrid kui ka mõned keerulisemad objektid või isegi funktsioonid. Maksimaalne elementide arv ühes massiivis on 4 292 967 295. Üritades lisada või lugeda sellest suurema indeksiga elementi, tekitab interpretaator veateate RangeError.

11.1.

Massiivi loomine

Masiivi saab luua peamiselt kahel viisil, massiiviliteraali ning massiivikonstruktori abil. Massiivi suurust ei pea eelnevalt määrama (kuigi see on võimalik), kuna massiivid on JavaScriptis dünaamilised. Kui lisada massiivi elemente, mille indeks on suurem kui massiivi pikkus, muudetakse massiiv automaatselt piisavalt suureks, nii et kasutatav indeks mahuks massiivi ära. Massiivi loomine läbi massiiviliteraali käib kandiliste sulgudega [], mille vahel on massiivi elemendid eraldatud omavahel komadega. var massiiv = [element1, element2, ..., elementN];

Sellisel juhul saame massiivi, mille elementideks on väärtused element1 .. elementN, kus indeksil 0 asub väärtus element1 ning indeksil N-1 asub väärtus elementN. Elemendi väärtust massiivist saame pärida operaatoriga [], sisestades kandiliste sulgude vahele soovitud elemendi indeksi. massiiv[0]; //element1

Teiseks kasutades konstruktorit Array. Konstruktori Array parameetritest sõltub milline massiiv 74 / 109


JavaScript, Andris Reinman

luuakse. Juhul kui parameetriks on ainult üks number, luuakse N (parameetriks saadud numbri väärtus) eeldefineeritud elemendiga massiiv, kus elementide väärtuseks on undefined. Juhul kui esimeseks parameetriks ei ole number või on parameetreid rohkem kui üks, luuakse massiiv sarnaselt massiiviliteraalidele. Järjekorras esimese parameetri väärtus seatakse indeksikohale 0, järgmine kohale 1 jne. var massiiv1 = new Array(); var massiiv2 = new Array(5); var massiiv3 = new Array(element1, element2, ..., elementN);

Näite esimesel real loome tühja massiivi, millel pole veel ühtegi elementi. Teisel real loome 5 eeldefineeritud elemendiga massiivi (elementide väärtusteks on undefined) ning kolmandal loome samasuguse massiivi nagu masiiviliteraalide näitegi korral.

11.2.

Mitmemõõtmelised massiivid

JavaScriptis ei ole võimalik luua mitmemõõtmelisi massiive nagu maatrikseid. Sama efekti on võimalik siiski saavutada, kasutades massiivi elementidena sisemisi massiive. var pos = [ [1,2,3], [2,3,1], [3,1,2]];

Sellisel juhul saab näiteks positsioonil (1,2), kus 1 asub Y teljel ning 2 asub X teljel, oleva väärtuse kätte järgnevalt pos[1][2]; //1

Seega pöördume kõigepealt massiivi nimega pos poole ja pärime sellest väärtust indeksi kohalt 1. Vastu saame aga uue massiivi ja pärime koheselt selle väärtust indeksil 2 ning alles nüüd saame kätte soovitud väärtuse, milleks näite juures on number 1 (teine rida, kolmas number). Kui me üritaks pärida massiivi elemendi väärtust nn. traditsionaalsel kujul pos[1,2], saaksime vastuseks hoopis massiivi kolmanda elemendiga (indeksi number 2) ehk siis väärtuse [3,1,2]. Ja seda seetõttu, et parameetri väärtus 1,2 tagastab tulemusena numbri 2. Kahe numbri vahel olev koma on erinevate lausete liitmise operaator. Seega operaator käivitab kõigepealt vasaku tehte (milleks on lihtsalt 1) ja seejärel parema tehte (milleks on lihtsalt 2) ning tagastab viimase tehte tulemuse ehk siis numbri 2. Kuna JavaScript on nõrgalt tüübitud keel, saab masiivi kasutada ka mitte-massiivi nõudvas kontekstis ilma veateadet tekitamata. See aga võib põhjustada algajate koodis raskesti avastatavaid vigu, kui ei olda massiivide olemusega päris hästi kursis ning üritatakse kasutada mitmemõõtelisi massiive. var dim = Array(2,2); dim[0,0] = 0; dim[0,1] = 1; dim[1,0] = 2; dim[1,1] = 3;

Tegu on täiesti korrektse ja töötava koodiga, ainult et see töötab täiesti valesti. Peale vaadates võiks arvata, et üritatakse luua 2×2 massiivi mille sisuks oleksid numbrid 0-3. 75 / 109


JavaScript, Andris Reinman |0,1| |2,3|

Tegelikkuses aga saab massiivi väärtuseks hoopis [2,3]

Ja seda seetõttu, et väärtuste omistamisel ei kasutatatud indeksite määramiseks mitte kuju [x][y], vaid [x,y], mis lahti kirjutatuna kujutab endast indeksit [y] (operaator koma , tagastab viimase operandi väärtuse).

11.3.

Massiivilaadse objekti teisendamine

JavaScriptis eksisteerib muutujaid mis näevad välja nagu massiivid ja käituvad nagu massiivid, aga tegelikult ei ole massiivid. Üheks selliseks on näiteks arguments parameeter, mille saab kaasa iga funktsioon. Samuti saab sarnaseid struktuure ka ise luua. Parameetril arguments asuvad väärtused numbriliste indeksite poolt määratud väljades, samuti on olemas elementide arvu näitav omadus length. Paraku aga puuduvad sellistel massiivilaadsetel objektidel massiiviobjektidele omased meetodid nagu slice või push. Nende lisamiseks tuleks objekt eelkõige „ehtsaks“ massiiviks teisendada. Otsest teisendusfunktsiooni selle jaoks pole, kuid võimalik on kombineerida kasutades ära massiivi prototüübi meetodit slice ja funktsiooni meetodit call. var massiiv = Array.prototype.slice.call(objekt);

Sellisel juhul käivitame konstruktori Array prototüübiobjektis oleva meetodi slice, edastades sellele läbi funktsiooni meetodi call objekti viitena massiivilaadse objekti. Kui meetod hakkab koostama tagastatavat massiivi ning kasutab selleks sisendina hetkel aktiivset objekti, on this väärtuseks meetodiga call edastatud objekt. Kuna teisi parameetreid meetodile slice edastatud pole, koostatakse tagastatav massiv kõikidest sisendmassiivi elementidest. Seega ongi tulemuseks omamoodi objekti teisendus massiiviks.

11.4.

Massiivi elementide kustutamine

Elemente saab massiivist kustutada operaatoriga delete. Meeles tuleb siiski pidada, et sellisel viisil elementide kustutamine ei muuda massiivi omaduse length väärtust. var m = [1,2,3,4,5]; delete m[2]; alert(m[2]); // undefined

Et vältida massiivi elementide kustutamisel sääraste „aukude“ tekkimist ning tagada vastavalt ka massivi omaduse length muutumine, tuleks elementide kustutamiseks kasutada massiivi meetodit splice.

11.5.

length

Number array.length Massiivi omadus length näitab elementide arvu massiivis. Tegu ei ole siiski „intelligentse“ omadusega - omadus ei arvesta mitte reaalset elementide arvu massiivis, vaid suurendab ühe võrra kõige suuremat massiivis olevat indeksit. 76 / 109


JavaScript, Andris Reinman var massiiv = []; massiiv[1000] = true; massiiv.length; // 1001

Tihti kasutatakse omadust ka massiivi uute elementide lisamisel. See on mugav juhul kui me ei tea eelnevalt ette palju elemente tuleb ja mis positsioonidel need asuvad. Seega võib uued elemendid lisada lihtsalt ükshaaval hetke massiivi lõppu, seades lisatava uueks viimaseks elemendiks. Sama saab tegelikult saavutada ka meetodiga push, millest tuleb juttu veidi hiljem. massiiv[massiiv.length] = elementX;

Omadust saab ka ise muuta. Juhul kui seada selleks massiivi elementide arvust suurem number, lisatakse massiivi lõppu vajalik arv undefined väärtusega elemente. Juhul kui seatav number on elementide arvust väiksem, kustutatakse massiivist kõik ülejäävad elemendid. massiiv.length = 5;

11.6.

Massiivide meetodid

Massiiviobjektidega kaasnevad mõningad kasulikud meetodid, mis aitavad massiividega läbi viia erinevaid vajalikke operatsioone. Näiteks push massivi lõppu elementide lisamiseks või concat massiivide liitmiseks. Need meetodid pole siiski osadel massiivilaadsetel JavaScripti objektidel saadaval ning seega tuleks sellised objektid eelnevalt ise massiivideks teisendada. JavaScript „omast tarkusest“ teisendamisega kahjuks hakkama ei saa. Erinevalt näiteks stringiobjektidest või numbritest, kui keeles olevad objekti meetodid ei muuda reeglina kunagi objekti enda väärtust, vaid genereerivad vastavalt saadud parameetritele tagastusväärtusena uue samatüübilise objekti, siis massiivide puhul osad meetodid muudavad ja osad mitte ka massiivi ennast. 11.6.1. concat Array massiiv.concat(mixed liidetav1 [, mixed liidetav2 [,… mixed liidetavN]]) Massiivi meetod concat liidab parameetrina saadud väärtused ning tagastab need liidetuna massiivile. Juhul kui parameetrina saadud väärtus on ka ise massiiv liidetakse selle elemendid lähtemasisivile ükshaaval eraldi väärtustena. var liitMassiiv = massiiv.concat(massiiv1, massiiv2 ..., massiivN); var massiiv = [1,2].concat(3, [4,5]); // [1,2,3,4,5]

11.6.2. join String array.join([String eraldaja]) Meetod join koostab massiivi elementidest stringi, teisendades kõik elemendid stringideks ning liites need omavahel parameetrina saadud eraldajaga. Juhul kui eraldajat tähistav parameeter on seadmata kasutatakse vaikimisi eraldajat, sümbolit koma ,. Üheks tüüpilisemaks juhuks meetodi join kasutamisel ongi nimekirja esitamine komadega eraldatult. Ilma eraldajata elementide liitmiseks võib eraldajaks märkida tühja stringi. var puuviljad = ["banaan", "õun", "pirn"]; 77 / 109


JavaScript, Andris Reinman puuviljad.join(); // banaan,õun,pirn puuviljad.join(", "); // banaan, õun, pirn puuviljad.join(" | "); // banaan | õun | pirn

11.6.3. pop mixed array.pop() Meetod eemaldab ja tagastab massiivi viimase elemendi. Kui massiiv on tühi, on tagastusväärtuseks undefined. Tegu on ühega neist meetoditest, mis muudavad ka massiivi ennast. var massiiv = [1,2,3,4,5]; var el = massiiv.pop(); alert(el); // 5 alert(massiiv); // [1,2,3,4]

11.6.4. push Number array.push(mixed liidetav1 [, mixed liidetav2 [,… mixed liidetavN]]) Meetod lisab parameetrina saadud elemendid ükshaaval massiivi lõppu. Erinevalt meetodist concat, mis arvestab ka parameetri tüübiga (massiivide elemendid lisatakse ükshaaval), lisab push elemendid tervikuna. var massiiv = []; massiiv.push(1,2,3,[4,5],6); massiiv; // [1,2,3,[4,5],6]

Koos meetodiga pop moodustavad meetodid massiivist pinumälu põhimõttel FILO, kus viimasena sisestatud element tagastatakse esimesena. var pinu = []; pinu.push(element1); pinu.push(element2); pinu.push(element3); pinu.pop(); // element3 pinu.pop(); // element2 pinu.pop(); // element1

Meetodi tagastusväärtuseks on liidetud massiivi elementide arv array.length. 11.6.5. reverse Array array.reverse() reverse

pöörab massiivi tagurpidi, nii et varem indeksil 0 asunud element hakkab peale meetodi rakendamist asuma massiivi viimasel indeksil. Meetodi tagastusväärtuseks on viit massiivi juurde. var massiiv = [1,2,3,4,5]; massiiv.reverse(); // [5,4,3,2,1]

78 / 109


JavaScript, Andris Reinman

11.6.6. shift mixed array.shift() Meetod eemaldab massiivist esimese elemendi ning tagastab selle väärtuse meetodi väljakutsekohta. shift on mõnevõrra aeglasem kui näiteks pop, kuna shift peab kõik massiivi elemendid uuesti indekseerima, samas kui pop piirdub lihtalt omaduse length vähendamisega. var massiv = [1,2,3,4,5]; var el = massiiv.shift(); alert(el); // 1 alert(massiiv); // [2,3,4,5]

11.6.7. slice Array array.slice(Number algus [, Number lõpp]) Meetod slice tagastab määratud osa massiivist uue massiivina ühe „lõikena“. Tagastusväärtuseks on küll uus massiiv, kuid juhul kui loodud massiivi elemendiks on objekt või muu keerulisem andmetüüp, ei ole tegu mitte omaette väärtusega, vaid viitega originaalse väärtuse juurde. Meetod võtab sisendiks kaks parameetrit, lõikekoha alguse ning lõpu indeksid. Juhul kui alguse positsioon on negatiivne number, loetakse seda massiivi lõpust. Näiteks -2 tähendab, et kaasatakse kaks viimast elementi. Juhul kui lõpu positsioon on määramata, kaasatakse kõik elemendid alates alguse positsioonist. var m1 = [1,2,3,{tekst: "külmkapp"}]; var m2 = m1.slice(1, 3); // [2, 3] var m3 = m1.slice(-2); // [3, {tekst: "külmkapp"}]

11.6.8. sort Array array.sort(Function sorteerija(mixed element1, mixed element2)) Meetod sort võtab parameetriks funktsiooni, mille alusel massiivi elemendid massiivis järjestada. Funktsioonile edastatavateks parameetriteks on kaks võrreldavat elementi. Kui funktsiooni tagastusväärtus on negatiivne, märgitakse esimene element eespool olevaks, aga kui mitte, siis märgitakse teine element eespool olevaks. var m = [4,1,5,2,3] m.sort(function(a,b){ return a - b; }); alert(m); // [1,2,3,4,5]

Juhul kui meetodile parameetriks funktsiooni ei ole antud, sorteeritakse massiiv tähestikulises järjekorras. See tähendab, et näiteks number "33" on väiksem kui "4", kuna tähestikulises järjestuses ei kontrollita vastavusi mitte terve väärtuse järgi, vaid sümboli haaval alates vasakult. Seega numbrite sorteerimiseks tuleb kasutada sarnast funktsiooni nagu eelnevas näites. Meetodiga on võimalik ka massiivi elemente juhuslikku järjekorda seada. Selle jaoks tuleks sorteerimisfunktsioonis siduda tagastusväärtus matemaatikafunktsiooni Math.random poolt genereeritud juhusliku numbriga. var m = [4,1,5,2,3] 79 / 109


JavaScript, Andris Reinman m.sort(function(a,b){ return 0.5 - Math.random(); }); alert(m);

11.6.9. splice Array array.splice(Number algus, Number elementide_arv [, mixed uus_element1 [, …, mixed uus_elementN]]) Meetod eemaldab massiivist määratud indeksilt etteantud hulga elemente ning vajadusel lisab samale positsioonile uued elemendid. Eemaldatavate ja lisatavate elementide arv ei pea olema võrdne. Samuti võib eemaldatatavate elementide hulgaks olla 0, misjärel muutub meetod hoopis andmete lisamise, mitte eemaldamise meetodiks Järgmises näites lisame meetodiga splice massiivi indeksile 2 neli uut elementi. var massiiv = ["põrand", "hunt", "ilves", "jänes"]; massiiv.splice(2,0,"kell", "laud", "sein", "karu");

Mille tulemusena saab massiiv oma uueks väärtuseks ["põrand", "hunt", "kell", "laud", "sein", "karu", "ilves", "jänes"]

Meetodi tagastusväärtuseks on massiivist eemaldatavad elemendid uue massiivi kujul. 11.6.10. unshift Number array.unshift(mixed liidetav1 [, mixed liidetav2 [,… mixed liidetavN]]) unshift

on sarnane meetodile push vahega, et kui push lisab väärtusi massiivi lõppu, siis unshift lisab väärtused massivi algusesse. Tegu on meetodi shift vastasmeetodiga. var massiiv = [3,4,5]; massiiv.unshift(1,2); alert(massiiv); // [1,2,3,4,5]

80 / 109


JavaScript, Andris Reinman

12.

Aeg

JavaScriptis on kõik kuupäevade ning aegadega seotud funktsioonid kogutud ühte objekti Date. Konstruktorfunktsiooni Date() on võimalik kasutada nii Date objekti loomiseks, kui ka tavafunktsioonina (sellisel juhul on tagastusväärtuseks hetke aeg stringi kujul). Samuti eksisteerivad mõned staatilised funktsioonid, mis kuuluvad vaid konstruktori enda juurde, mitte sellest tuletatud objektidele. Viimase näiteks oleks funktsioon Date.parse() tekstilisel kujul oleva ajastringi teisendamiseks ajaobjektiks. Vastavalt standardile peab JavaScripti Date objekt olema võimeline esitama iga kuupäeva ja kellaaega millisekundi täpsusega 100 miljonit päeva enne ja peale 1. jaanuarit 1970. See tähendab umbkaudu +/- 273 785 aastat. Võrdluseks laialtlevinud Unix/POSIX timestamp loendur mis enamustes süsteemides on 32 bitine, ammendub juba 19. jaanuaril 2038.

12.1.

Ajatempel

Ajatempel kujutab endast täisarvulist numbrit, mis tähistab kindlat aega. Selline numbriline kuju teeb erinevad arvutused aegadega suhteliselt lihtsaks. Kui näiteks keeltes PHP või Python on ajatempel kujul Unix/POSIX timestamp tähistades sekundite arvu alates 1. jaanuarist 1970, siis JavaScripti ajatempel loeb samast hetkest hoopis millisekundeid. Thu Jun 04 2009 20:35:16 GMT+0300 (EEST) Unix/POSIX: 1244136916 JavaScript: 1244136916000

Tänu numbrilisele kujule on suhteliselt kerge leida kuupäevi alates- või enne mingit kindlat aega. Näiteks tänasest 30 päeva pärast oleva kuupäeva leiab järgnevalt. var d = new Date(new Date().getTime() + 1000*3600*24*30);

Arvutus 1000*3600*24*30 tähendab 30 päeva millisekundites ning täpsemalt oleks see 1000 millisekundit * 3600 sekundit (1 tund) * 24 tundi (1 päev) * 30 päeva.

12.2.

Date

Konstruktorfunktsiooni Date() saab operaatoriga new käivitada neljal erineval viisil. Kõikidel juhtudel on tulemuseks Date objekt, mis sisaldab mingit kindlat, konstruktorfunktsiooni sisendparameetritest sõltuvat aega. Objekti meetodite abil on siis võimalik selle saadud ajaväärtusega manipuleerida, tagastada ainult osa kuupäevast vms. new new new new

Date(); Date(ajatempel); Date(aeg_teksti_kujul); Date(aasta, kuu [, päev, tund, minut, sekund, ms]);

Juhul kui parameetrit pole määratud, saab loodava objekti ajaväärtuseks objekti loomise aeg. Ajatempel sisendina tähendab millisekundeid alates 1. jaanuar 1970. Aeg teksti kujul peab olema JavaScripti jaoks arusaadaval kujul, kahjuks näiteks MySQL DATETIME formaat YYYY-MM-DD HH:MM:SS selle jaoks ei sobi, tagastades vigase ajaväärtuse. Võimalik oleks aga kasutada kuju MM/DD/YYYY HH:MM:SS mis tuntakse ilusti ära. Üldiselt on toetatavad tekstiformaadid sõltuvad platvormist, seega tegelikult ei saa ühegi formaadi puhul teisenduse õigsuses lõpuni kindel olla. 81 / 109


JavaScript, Andris Reinman

Üksikute aja ja kuupäeva elementide esitamisel parameetritena numbrilisel kujul, on aasta ja kuu väärtused kohustuslikud ning ülejäänud 5 parameetrit valikulised. Juhul kui sisendiks anda ainult ainult aasta, peab funktsioon seda hoopis ajatempliks ja tagastab mitteoodatud tulemuse. Juhul kui Date() on käivitatud ilma operaatorita new, jätab funktsioon parameetrid arvesse võtmata ning tagastab hetke aja stringi kujul. Meeles tuleks ka pidada, et parameetrina antud aeg (kui selles pole üheselt märgitud ajatsooni näiteks GMT+0100 (Saksamaa)), tähistab alati lokaalset aega.

12.3.

Meetodid

Date

objekt sisaldab terve hulga erinevaid kasulikke meetodeid, mis abistavad ajaväärtustega tegelemisel. 12.3.1. getDate Number date.getDate() Meetod getDate tagastab Date objektis määratud lokaalse aja kuupäeva väärtuse vahemikus 1..31. var aeg = new Date(2000,1,1); aeg.getDate(); // 1

12.3.2. getDay Number date.getDay() Meetod getDay tagastab Date objektis määratud lokaalse aja nädalapäeva väärtuse vahemikus 0..6. Väärtus 0 tähistab pühapäeva ning väärtused 1..6 esmaspäeva-laupäeva. 12.3.3. getFullYear Number date.getFullYear() Meetod getFullYear tagastab Date objektis määratud lokaalse aja aasta väärtuse neljakohalise numbrina. new Date().getFullYear(); // 2009

12.3.4. getHours Number date.getHours() Meetod getHours tagastab Date objektis määratud lokaalse aja tunni väärtuse vahemikus 0..23. 12.3.5. getMilliseconds Number date.getMilliseconds() Meetod getMilliseconds tagastab Date objektis määratud lokaalse aja millisekundite väärtuse viimasest sekundist vahemikus 0..999. 12.3.6. getMinutes Number date.getMinutes() 82 / 109


JavaScript, Andris Reinman

Meetod getMinutes tagastab Date objektis määratud lokaalse aja minutite väärtuse viimasest tunnist vahemikus 0..59. 12.3.7. getMonth Number date.getMonth() Meetod getMonth tagastab Date objektis määratud lokaalse aja kuu väärtuse vahemikus 0..11, kus 0 on jaanuar ning 11 detsember. 12.3.8. getSeconds Number date.getSeconds() Meetod getSeconds tagastab Date objektis määratud lokaalse aja sekundite väärtuse viimasest minutist vahemikus 0..59. 12.3.9. getTime Number date.getTime() Meetod getTime tagastab Date objektis määratud lokaalse aja väärtuse täisnumbri kujul millisekunditena alates 1. jaanuarist 1970. Sellisel numbrilise kujul aja esitamine on kasulik kahe erineva aja vahel seose leidmiseks - kas siis teades kindlat vahemikku (näiteks 30 päeva) teada saada teist kuupäeva seoses olemasolevaga või näiteks kahe kuupäeva vahelise aja leidmiseks. var d = new Date(new Date().getTime() + (100*3600*24*30)); alert('30 päeva pärast on aeg '+d); var p = (new Date(2100,1,1).getTime() - new Date().getTime())/(100*3600*24) alert('Aastani 2100 on veel jäänud '+p+' päeva');

12.3.10. getTimezoneOffset Number date.getTimezoneOffset() Meetod getTimezoneOffset tagastab Date objektis määratud lokaalse aja erinevuse GMT ajavööndi ajast minutites. Eestis on selleks väärtuseks talvel -120 ning suvel -180. Antud suurus on esitatud tundide asemel minutites, kuna osades riikides ei ole ajavööndid täistunnillise väärtusega, näiteks Indias on ajavöönd -05:30. Kasulik on seda väärtust teada juhul kui soovitakse suvalises maailma punktis asuvale kasutajale näidata aega sõltuvalt tema asukohast. Server annab veebilehele aja mingi kindla ajavööndi, näiteks GMT järgi ning veebilehel olev JavaScript kirjutab selle aja vastavalt kasutaja enda vööndile dünaamiliselt üle. 12.3.11. getUTCDate Number date.getUTCDate() Meetod getUTCDate tagastab Date objektis määratud aja universaalse vormi (GMT vööndi järgi) kuupäeva väärtuse vahemikus 1..31. 12.3.12. getUTCDay Number date.getUTCDay() 83 / 109


JavaScript, Andris Reinman

Meetod getUTCDay tagastab Date objektis määratud aja universaalse vormi (GMT vööndi järgi) nädalapäeva väärtuse vahemikus 0..6. Väärtus 0 tähistab pühapäeva ning väärtused 1..6 esmaspäeva-laupäeva. 12.3.13. getUTCFullYear Number date.getUTCFullYear() Meetod getUTCFullYear tagastab Date objektis määratud aja universaalse vormi (GMT vööndi järgi) aasta väärtuse neljakohalise numbrina. 12.3.14. getUTCHours Number date.getUTCHours() Meetod getUTCHours tagastab Date objektis määratud aja universaalse vormi (GMT vööndi järgi) tunni väärtuse vahemikus 0..23. 12.3.15. getUTCMilliseconds Number date.getUTCMilliseconds() Meetod getUTCMilliseconds tagastab Date objektis määratud aja universaalse vormi (GMT vööndi järgi) millisekundite väärtuse viimasest sekundist vahemikus 0..999. 12.3.16. getUTCMinutes Number date.getUTCMinutes() Meetod getUTCMinutes tagastab Date objektis määratud aja universaalse vormi (GMT vööndi järgi) minutite väärtuse viimasest tunnist vahemikus 0..59. 12.3.17. getUTCMonth Number date.getUTCMonth() Meetod getUTCMonth tagastab Date objektis määratud aja universaalse vormi (GMT vööndi järgi) kuu väärtuse vahemikus 0..11, kus 0 on jaanuar ning 11 detsember. 12.3.18. getUTCSeconds() Number date.getUTCSeconds() Meetod getUTCSeconds tagastab Date objektis määratud aja universaalse vormi (GMT vööndi järgi) sekundite väärtuse viimasest minutist vahemikus 0..59. 12.3.19. getYear Number date.getYear() Meetod getYear tagastab Date objektis oleva aja aasta väärtuse, millest lahutatakse suurus 1900. Algselt oli see mõeldud kahekohalise aastanumbri leidmiseks (nt. 1996 - 1900 = 96), kuid alates aastast 2000 on funktsioon muutunud sisuliselt kasutuks, tagastades aasta väärtuseks segasevõitu kolmekohalise numbri. new Date().getYear(); // 109

Meetodi getYear asemel tuleks õige tulemuse saamiseks kasutada meetodit getFullYear. 84 / 109


JavaScript, Andris Reinman

12.3.20. parse Number Date.parse(String ajastring) Meetod Date.parse on globaalse objekti Date staatiliselt meetodiks. See tähendab, et meetod ei liigu Date tüüpi objektide loomisel uute objektide juurde kaasa. Meetod võtab sisendiks stringi kujul ajaväärtuse ja teisendab selle millisekundite kujul ajatempliks. var t = Date.parse("12/24/2009 13:30:00"); alert(t); // 1261650600000

Meetod on kasulik juhul, kui on tarvis teisendada ajastring ajatempliks, kuid ei soovita luua selle jaoks uut Date tüüpi objekti. 12.3.21. setDate Number date.setDate(Number päev) Meetod setDate võtab parameetriks kuupäeva (kohaliku aja järgi) vahemikus 1..31 ning seab selle Date objektiga seotud aja kuupäevaks. Meetodi tagastusväärtuseks on saadud aeg millisekundites. var d = new Date(2000,3,13); d.setDate(14); // 955659600000

12.3.22. setFullYear Number date.setFullYear(Number aasta [, Number kuu [, Number päev]]) Meetod setFullYear võtab parameetriks neljakohalise numbriga aasta (kohaliku aja järgi) ning seab selle Date objektiga seotud aja aastaks. Meetodi tagastusväärtuseks on saadud aeg millisekundites. Valikuliselt on sama meetodiga võimalik seada ka kuud ning kuupäeva. Selleks tuleks kasutada kahte lisaparameetrit kuu (vahemikus 0..11) ning päev (vahemikus 1..31). 12.3.23. setHours Number date.setHours(Number tund [, Number minut [, Number sekund [, Number ms]]])

Meetod setHours võtab parameetriks tunni (kohaliku aja järgi) vahemikus 0..23 ning seab selle Date objektiga seotud aja tunniks. Meetodi tagastusväärtuseks on saadud aeg millisekundites. Meetodil on veel kolm valikulist lisaparameetrit, millega saab seada ka minutit, sekundit ja millisekundit. 12.3.24. setMilliseconds Number date.setMilliseconds(Number ms) Meetod võimaldab seada Date objekti millisekundiosa väärtust (kohaliku aja järgi). Parameeter ms peab olema vahemikus 0..999. Meetodi tagastusväärtuseks on saadud aeg millisekundites. 12.3.25. setMinutes Number date.setMinutes(Number minutid [, Number sekund [, Number ms]]) Meetod setMinutes võtab parameetriks minuti väärtuse (kohaliku aja järgi) vahemikus 0..59 ning 85 / 109


JavaScript, Andris Reinman

seab selle Date objektiga seotud aja minuti väärtuseks. Meetodi tagastusväärtuseks on saadud aeg millisekundites. Meetodil on veel kaks valikulist lisaparameetrit, millega saab seada ka sekundit ja millisekundit. 12.3.26. setMonth Number date.setMonth(Number kuu [, Number päev]) Meetod setMonth võtab parameetriks kuu väärtuse (kohaliku aja järgi) vahemikus 0..11 ning seab selle Date objektiga seotud aja kuu väärtuseks. Meetodi tagastusväärtuseks on saadud aeg millisekundites. Valikuliselt on sama meetodiga võimalik seada ka kuupäeva. Selleks tuleks kasutada kuupäeva lisaparameetrit, kus kuupäev on vahemikus 1..31. 12.3.27. setSeconds Number date.setSeconds(Number sekund [, Number ms]) Meetod setSeconds võtab parameetriks sekundi väärtuse (kohaliku aja järgi) vahemikus 0..59 ning seab selle Date objektiga seotud aja sekundi väärtuseks. Meetodi tagastusväärtuseks on saadud aeg millisekundites. Meetodil on veel valikuline lisaparameeter, millega saab seada ka millisekundit. 12.3.28. setTime Number date.setTime(Number ajatempel) Meetodiga saab seada Date objekti ajaväärtust andes sellele parameetriks ajatempli millisekundite kujul. Ajatempli genereerimiseks on mugav kasutada funktsiooni Date.parse. var d = new Date(); d.setTime(Date.parse('2005/12/31 15:50:00')); // 1136033400000

Meetodi tagastusväärtuseks on sisendiks saadud millisekundite väärtus. 12.3.29. setUTCDate Number date.setUTCDate(Number päev) Meetod setUTCDate võtab parameetriks kuupäeva (universaalse GMT aja järgi) vahemikus 1..31 ning seab selle Date objektiga seotud aja kuupäevaks. Meetodi tagastusväärtuseks on saadud aeg millisekundites. var d = new Date(2000,3,13); d.setUTCDate(14); // 955746000000

12.3.30. setUTCFullYear Number date.setUTCFullYear(Number aasta [, Number kuu [, Number päev]]) Meetod setUTCFullYear võtab parameetriks neljakohalise numbriga aasta (universaalse GMT järgi) ning seab selle Date objektiga seotud aja aastaks. Meetodi tagastusväärtuseks on saadud aeg millisekundites. Valikuliselt on sama meetodiga võimalik seada ka kuud ning kuupäeva. Selleks tuleks kasutada 86 / 109


JavaScript, Andris Reinman

kahte lisaparameetrit kuu (vahemikus 0..11) ning päev (vahemikus 1..31). 12.3.31. setUTCHours Number date.setUTCHours(Number tund [, Number minut [, Number sekund [, Number ms]]]) Meetod setUTCHours võtab parameetriks tunni (universaalse GMT järgi) vahemikus 0..23 ning seab selle Date objektiga seotud aja tunniks. Meetodi tagastusväärtuseks on saadud aeg millisekundites. Meetodil on veel kolm valikulist lisaparameetrit, millega saab seada ka minutit, sekundit ja millisekundit. 12.3.32. setUTCMilliseconds Number date.setUTCMilliseconds(Number ms) Meetod võimaldab seada Date objekti millisekundiosa väärtust (universaalse GMT järgi). Parameeter ms peab olema vahemikus 0..999. Meetodi tagastusväärtuseks on saadud aeg millisekundites. 12.3.33. setUTCMinutes Number date.setUTCMinutes(Number minutid [, Number sekund [, Number ms]]) Meetod setUTCMinutes võtab parameetriks minuti väärtuse (universaalse GMT järgi) vahemikus 0..59 ning seab selle Date objektiga seotud aja minuti väärtuseks. Meetodi tagastusväärtuseks on saadud aeg millisekundites. Meetodil on veel kaks valikulist lisaparameetrit, millega saab seada ka sekundit ja millisekundit. 12.3.34. setUTCMonth Number date.setUTCMonth(Number kuu [, Number päev]) Meetod setUTCMonth võtab parameetriks kuu väärtuse (universaalse GMT järgi) vahemikus 0..11 ning seab selle Date objektiga seotud aja kuu väärtuseks. Meetodi tagastusväärtuseks on saadud aeg millisekundites. Valikuliselt on sama meetodiga võimalik seada ka kuupäeva. Selleks tuleks kasutada lisaparameetrit päev (vahemikus 1..31). 12.3.35. setUTCSeconds Number date.setUTCSeconds(Number sekund [, Number ms]) Meetod setUTCSeconds võtab parameetriks sekundi väärtuse (universaalse GMT järgi) vahemikus 0..59 ning seab selle Date objektiga seotud aja sekundi väärtuseks. Meetodi tagastusväärtuseks on saadud aeg millisekundites. Meetodil on veel valikuline lisaparameeter, millega saab seada ka millisekundit. 12.3.36. setYear Number date.setYear(Number aasta) Meetod setYear võtab sisendiks aasta väärtuse (kohaliku aja järgi). Juhul kui aasta väärtus jääb vahemikku 0..99, liidetakse sellele väärtus 1900. Tegu on praeguseks ajaks suhteliselt kasutu featuuriga ning seega tuleb jääda neljakohaliste numbrite juurde. 87 / 109


JavaScript, Andris Reinman

12.3.37. toDateString String date.toDateString() Meetod väljastab kuupäeva väärtuse kohaliku aja järgi stringina inimloetaval kujul. Täpne vorm sõltub kasutatavast platvormist. new Date().toDateString(); // Fri Jun 05 2009

12.3.38. toGMTString String date.toGMTString() Meetod väljastab kuupäeva ja aja väärtuse universaalse GMT aja järgi stringina inimloetaval kujul. Täpne vorm sõltub kasutatavast platvormist. new Date().toGMTString(); // Thu, 04 Jun 2009 22:10:17 GMT

12.3.39. toLocaleDateString String date.toLocaleDateString() Meetod väljastab kuupäeva väärtuse kohaliku aja järgi stringina inimloetaval kujul, arvestades kasutaja lokaali. Täpne vorm sõltub kasutatavast platvormist. new Date().toLocaleDateString(); // 06/05/2009

12.3.40. toLocaleString String date.toLocaleString() Meetod väljastab kuupäeva ja aja väärtuse kohaliku aja järgi stringina inimloetaval kujul, arvestades kasutaja lokaali. Täpne vorm sõltub kasutatavast platvormist. new Date().toLocaleString(); // Fri Jun 5 01:14:31 2009

12.3.41. toLocaleTimeString String date.toLocaleTimeString() Meetod väljastab aja väärtuse kohaliku aja järgi stringina inimloetaval kujul, arvestades kasutaja lokaali. Täpne vorm sõltub kasutatavast platvormist. new Date().toLocaleTimeString(); // 01:15:54

12.3.42. toString String date.toString() Meetod toString tagastab kuupäeva ja aja väärtuse kohaliku järgi stringina inimloetaval kujul. Täpne vorm sõltub kasutatavast platvormist.

88 / 109


JavaScript, Andris Reinman new Date().toString(); // Fri Jun 05 2009 01:19:57 GMT+0300 (EEST)

12.3.43. toTimeString String date.toTimeString() Meetod väljastab aja väärtuse kohaliku aja järgi stringina inimloetaval kujul. Täpne vorm sõltub kasutatavast platvormist. new Date().toTimeString(); // 01:17:08 GMT+0300 (EEST)

12.3.44. toUTCString String date.toUTCString() Meetod väljastab kuupäeva ja aja väärtuse universaalse GMT vööndiaja järgi stringina inimloetaval kujul. Täpne vorm sõltub kasutatavast platvormist. new Date().toLocaleString(); // Thu, 04 Jun 2009 22:17:33 GMT

12.3.45. UTC Number Date.UTC([Number aasta [, Number kuu [, Number päev [, Number tund [, Number minut [, Number sekund [, Number ms]]]]]]]) Meetod UTC on sarnaselt Date.parse meetodiga globaalse objekti Date staatiliseks meetodiks. Meetod võtab sisendiks GMT ajavööndi aja 7 parameetri kujul ning tagastab ajatempli millisekunditena. Kasutatavad 7 parameetrit on kõik valikulised. Meetodit on mugav kasutada Date objekti loomiseks, kui teada on universaalne GTM aeg, kuid konstruktor Date eeldab lokaalset aega. var d = new Date(Date.UTC(aasta, kuu, päev, tund, minut, sekund, ms));

Sellisel juhul loob Date.UTC GMT aja järgi ajatempli (mis on alati universaalne) ning edastab selle konstruktorfunktsiooni Date parameetriks. 12.3.46. valueOf Number date.valueOf() Sama mis getTime. Meetod tagastab Date objekti ajaväärtuse ajatemplina millisekundite väärtusena. Meetod on vajalik teisendusteks, kus Date objekti üritatakse kasutada numbrilises kontekstis.

89 / 109


JavaScript, Andris Reinman

13.

Matemaatika

Matemaatikafunktsioonid (ümardamine, siinuse leidmine jms.) erinevalt näiteks funktsioonist parseInt ei ole JavaScriptis globaalsed funktsioonid, vaid eritüübilise objekti Math meetoditeks. See tähendab, et ümardusfunktsiooni round saab kasutada vaid läbi matemaatikaobjekti. var ymardus = Math.round(3.34); // 3 Math

puhul ei ole tegu konstruktorfunktsiooniga nagu String või Number, vaid objektiga. Seega pole võimalik luua operaatoriga new uusi Math tüüpi objekte. Proovides seda siiski teha var minuMath = new Math();

Tagastab interpretaator veateate TypeError: Math is not a constructor

Küll aga on võimalik objekti, nagu kõiki muid kloonida, kasutades selleks Objektide peatükis toodud funktsiooni copy. function copy(object) { function F() {} F.prototype = object; return new F(); } var myMath = copy(Math); myMath.g = 9.81; alert(myMath.ceil(myMath.g)); // 10 alert(Math.g); // undefined

Näites lõime objektist Math koopia myMath ja lisasime sellele omaduse g väärtusega 9.81. Seega objekt myMath sai prototüübiahelat pidi enda kasutusse kõik objekti Math meetodid ja omadused ning lisaks veel ühe unikaalse omaduse, mida originaalsel Math objektil pole. Näidatud viisil Math objekti kloonimine pole siiski eriti mõistlik (ei anna midagi juurde ning muudab programmikoodi loetavust halvemaks) ja on siin ära toodud vaid illustratiivse näitena.

13.1.

Konstandid

Math

objektis on objekti omaduste näol defineeritud mitmed matemaatilised konstandid, mida saab vajadusel matemaatilistes tehetes kasutada. 13.1.1. Math.E Number Math.E Konstant e (Euleri arv) on naturaallogaritmi aluseks. Kuigi tegu on irratsionaalarvuga, mis tähendab et selle väärtust ei saa täpselt esitada, on JavaScriptis konstandil siiski lõpliku pikkusega väärtus. Math.E == 2.718281828459045.

90 / 109


JavaScript, Andris Reinman

Matemaatiliste konstantide numbrilised väärtused siin ja edaspidi on ligikaudsed ning sõltuvad kasutatavast platvormist.

13.1.2. Math.LN10 Number Math.LN10 LN10

on arvu 10 naturaallogaritmi väärtus. Math.LN10 == 2.302585092994046

13.1.3. Math.LN2 Number Math.LN2 LN2

on arvu 2 naturaallogaritmi väärtus. Math.LN2 == 0.6931471805599453

13.1.4. Math.LOG10E Number Math.LOG10E LOG10E

on arvu e logaritm alusel 10. Math.LOG10E == 0.4342944819032518

13.1.5. Math.LOG2E Number Math.LOG2E LOG2E

on arvu 2 logaritm alusel 10. Math.LOG2E == 1.4426950408889634

13.1.6. Math.PI Number Math.PI PI

esitab matemaatilise konstandi (pii) väärtust. Tegu on ringi ümbermõõdu ja diameetri pikkuse jagatisega. Math.PI == 3.141592653589793 13.1.7. Math.SQRT1_2 Number Math.SQRT1_2 SQRT1_2

tähistab jagatist numbri 1 jagamisel ruutjuurega numbrist 2.

Math.SQRT1_2 =

== 0.7071067811865476

13.1.8. Math.SQRT2 Number Math.SQRT2 Konstant Math.SQRT2 tähistab ruutjuure väärtust arvust 2. Math.SQRT2 =

== 1.4142135623730951

91 / 109


JavaScript, Andris Reinman

13.2.

Meetodid

Objektil Math on terve hulk erinevaid meetodeid, mis aitavad läbi viia vajalikke matemaatilisi tegevusi. Kuigi need matemaatikafunktsioonid on defineeritud objekti Math meetoditena, on tegu siiski täiesti staatiliste funktsioonidega - funktsioonide tööks objekti Math ennast ei kasutata ning selle väärtusi ei muudeta. Math objekti puhul on tegu rohkem eraldi nimeruumi kui objektiga objekti mõistes, erinevad matemaatilise sisuga funktsioonid on kogutud ühte kindlasse konteinerisse kokku. 13.2.1. Math.abs Number Math.abs(Number väärtus) Funktsioon Math.abs(nr) tagastab parameetrina saadud numbri absoluutväärtuse. Positiivse numbri korral jääb väärtus samaks, negatiivse numbri korral muudetakse märk positiivseks. var nr; nr = Math.abs(30); // 30 nr = Math.abs(-30); // 30

13.2.2. Math.acos Number Math.abs(Number arv) Meetod acos tagastab arvu arkuskoosinuse, tegu on koosinuse pöördfunktsiooniga. Tagastusväärtuseks saadud nurk on radiaankujul vahemikus 0..π. var nurk = Math.acos(cos);

13.2.3. Math.asin Number Math.abs(Number arv) Meetod asin tagastab arvu arkussiinuse, tegu on siinuse pöördfunktsiooniga. Tagastusväärtuseks saadud nurk on radiaankujul vahemikus -π/2..π/2. var nurk = Math.asin(sin);

13.2.4. Math.atan Number Math.atan(Number arv) Meetod atan tagastab arvu arkustangensi, tegu on tangensi pöördfunktsiooniga. Tagastusväärtuseks saadud nurk on radiaankujul vahemikus -π/2..π/2. var nurk = Math.atan(tan);

13.2.5. Math.atan2 Number Math.atan2(Number x, Number y) Meetod atan2 leiab arkustangensi parameetritest x ja y radiaanides vahemikus - .. .

92 / 109


JavaScript, Andris Reinman

13.2.6. Math.ceil Number Math.ceil(Number arv) Meetod ceil ümardab arvu ülemise täisnumbrini. var nr; nr = Math.ceil(3.0); // 3 nr = Math.ceil(3.1); // 4

13.2.7. Math.cos Number Math.cos(Number nurk) Meetod cos tagastab parameetrina saadud nurga koosinuse, milleks on täisnurkse kolmnurga mittetäisnurkse nurga lähiskaateti b ning selle täisnurkse kolmnurga hüpotenuusi c pikkuse jagatis. var cos = Math.cos(nurk);

Funktsioon ootab parameetriks nurga suurust radiaanides. Radiaanid saab teisendada kraadideks konstandi abil. var kraadid = radiaanid * (Math.PI/360);

13.2.8. Math.exp Number Math.exp(Number x) Meetod exp tagastab väärtuse e astmes x. Math.E == Math.exp(1)

13.2.9. Math.floor Number Math.floor(Number arv) Meetod floor ümardab arvu alumise täisnumbrini. Juhul kui tegu on negatiivse numbriga, ümardatakse number suurima negatiivse väärtuse, mitte nulli poole. var nr; nr = Math.floor(3.0); // 3 nr = Math.floor(3.9); // 3 nr = Math.floor(-3.9); // -4

13.2.10. Math.log Number Math.log(Number x) Meetod log võtab sisendiks nullist suurema positiivse väärtusega numbri x ning tagastab sellest naturaallogaritmi

. 93 / 109


JavaScript, Andris Reinman

Läbi naturaallogaritmi saab järgmiste funktsioonidega leida ka kümnendlogaritme ning kahendlogaritme. var log10 = function(x){ return Math.LOG10E * Math.log(x); }; var log2 = function(x){ return Math.LOG2E * Math.log(x); };

13.2.11. Math.max Number Math.max(mixed parameetrid) Meetod max võtab parameetritena suvalise arvu väärtuseid ning tagastab neist suurima. Juhul kui sisendparameetreid pole, on tagastusväärtuseks negatiivse lõpmatuse väärtus -Infinity ning juhul kui mõni sisendparameetritest on NaN või pole teisendatav numbriks, on tagastusväärtuseks NaN. var nr; nr = Math.max(3,5,-1); // 5 nr = Math.max(); // -Infinity nr = Math.max(3,5,"r"); // NaN

13.2.12. Math.min Number Math.min(mixed parameetrid) Meetod Math.min võtab parameetritena suvalise arvu väärtuseid ning tagastab neist vähima. Juhul kui sisendparameetreid pole, on tagastusväärtuseks lõpmatuse väärtus Infinity ning juhul kui mõni sisendparameetritest on NaN või pole teisendatav numbriks, on tagastusväärtuseks NaN. var nr; nr = Math.min(3,5,-1); // -1 nr = Math.min(); // Infinity nr = Math.min(3,5,"r"); // NaN

13.2.13. Math.pow Number Math.pow(Number x, Number y) Meetod pow tagastab väärtuse x astmes y. Math.pow(x,y) =

. Juhul kui avaldise tulemuseks on

kompleksarv kujul a+bi, kus i tähistab imaginaarühikut i = , tagastab funktsioon eriväärtuse NaN. Seega negatiivse x väärtuse korral peaks y olema positiivne või negatiivne täisarv. Murdarvuline aste tähendab arvust n-astmel juure võtmist, kui y oleks esitatav kujul täisarvud). Seega avaldise saab murdarvulise astme korral lahti kirjutada kujule negatiivse arvu x puhul oleks selle avaldise tulemuseks kompleksarv.

(m ning n on ning

94 / 109


JavaScript, Andris Reinman var nr; nr = Math.pow(4, 2); // 16 nr = Math.pow(5, -2); // 0.04 = 1/5^2 = 1/25 nr = Math.pow(-3, -0.5); //NaN, tulemus on kompleksarv

13.2.14. Math.random Number Math.random() Meetod random tagastab pseudojuhusliku numbri vahemikus 0..1 kus 0 kuulub hulka, kuid 1 mitte. Pseudojuhuslik tähendab seda, et juhusliku numbri genereerimiseks kasutatakse lõpliku pikkusega nihkeregistrit. Kui tõeliselt juhusliku numbri puhul ei sõltu numbri tulemine mitte kuidagi eelmistest väärtustest, on pseudojuhusliku numbri korral iga järgmise numbri väärtus üheselt määratud eelmiste numbritega. Nihkeregistri sama väärtusega lähtestamise korral (selleks kasutatakse tegelikult hetke aega, mis on pidevas muutumises) oleks numbrite järjestus juhuslike numbrite genreerimisel täpselt sama. Reeglina on pseudojuhuslik number ikkagi tava-programmide jaoks piisavalt juhuslik. var nr = Math.random(); // 0.00 .. 0.99

Kuna üldiselt on juhuslikku numbrit vaja mingis kindlas vahemikus, saab seda kergelt teha juhusliku numbri korrutamises ülemise piiriga. Sellisel juhul muutub genereeritud juhuslik number omamoodi protsendiks maksimaalsest limiidist. Kuna aga väärtus 1 ei tule juhuslikku numbrit genreerides kunagi välja, tuleb maksimaalse limiidi kaasamiseks liita limiidile väärtus 1 ning võtta saadud numbrist ainult täisosa. Niiviisi on tagatud, et kõik numbrid vastavas vahemikus on võrdselt esinevad. function juhuslik(limiit){ var nr = Math.floor(Math.random()*(limiit+1)) } var nr = juhuslik(100); // 0 .. 100

13.2.15. Math.round Number Math.round(Number arv) Meetod round ümardab numbri lähima täisarvuni. Alates murdosa väärtusest 0.5 ümardatakse number üles, väiksema väärtuse korral alla. var nr; nr = Math.round(4.3); // 4 nr = Math.round(4.5); // 5

13.2.16. Math.sin Number Math.sin(Number nurk) Meetod sin tagastab parameetrina saadud nurga siinuse, milleks on täisnurkse kolmnurga mittetäisnurkse nurga vastaskaateti a ning selle täisnurkse kolmnurga hüpotenuusi c pikkuse jagatis. var sin = Math.sin(nurk); 95 / 109


JavaScript, Andris Reinman

13.2.17. Math.sqrt Number Math.sqrt(Number arv) Meetod sqrt leiab numbri ruutjuure. Numbri väärtus peab olema positiivne reaalarv või 0. Negatiivse väärtuse korral on tagastusväärtuseks eriväärtus NaN. var nr nr = Math.sqrt(4); // 2 nr = Math.sqrt(-4); // NaN

Juhul kui on vaja leida mingit muud juurt peale ruutjuure, saab seda teha funktsiooniga Math.pow, kasutades arvu astmeks murdarvu. Näiteks kuupjuurt arvust x saab leida järgmise avaldisega. var nr; nr = Math.pow(x,1/3); //kuupjuur

13.2.18. Math.tan Number Math.tan(Number nurk) Meetod Math.tan(nurk) leiab parameetrina saadud nurga tangensi. Tangens on täisnurkse kolmnurga mittetäisnurkse nurga vastaskaateti a ning lähiskaateti b pikkuse jagatis. var tan = Math.tan(nurk);

Funktsioon ootab parameetriks nurga suurust radiaanides.

96 / 109


JavaScript, Andris Reinman

14.

Nimeruumid

Nimeruum on üldjaotatud nimekogum, milles kõik nimed on ühesed, pakkudes konteksti erinevate muutujate ja funktsioonide üheseks defineerimiseks. Näiteks kui programmis on defineeritud mingi funktsioon, mis võib minna konflikti teise samas programmis oleva funktsiooniga (funktsioonid on deklareeritud sama nimega), võib probleemi ennetamiseks lülitada selle funktsiooni hoopis mõnda sobivasse nimeruumi. Nimede ühesuse probleem tekib peamiselt, kui kasutatakse ühes programmis korraga erinevaid teeke - võib juhtuda, et erinevates teekides on deklareeritud sama nimega funktsioonid, mis tegelikult on täiesti erineva funktsionaalsusega. Taolise probleemi lahendamiseks nimeruume kasutataksegi. JavaScriptis saab nimeruume luua läbi objektide - selle asemel, et deklareerida funktsioon globaalses skoobis, defineerime selle mõne kindla objekti meetodina. Nii saab objektist nimeruumi kandja ning loodud meetodist nimeruumis asuv funktsioon. if(!window.NIMERUUM){ NIMERUUM = {} } NIMERUUM.alert = function(tekst){ document.write(tekst); } alert(123); NIMERUUM.alert(123);

Näites kontrollime esiteks, kas globaalses objektis (brauseris on selleks window) on nimeruumi objekt NIMERUUM juba olemas ning kui ei ole, siis loome selle. Seejärel lisame nimeruumi uue funktsiooni alert, mis väljastab sisendi brauseri aknasse käsuga document.write. Niiviisi saame deklareerida funktsiooni nimega alert, ilma et see läheks konflikti globaalse skoobi funktsiooniga alert. Sellisel objektide abil loodud JavaScripti nimeruumid on hirerahilised, kuna nimeruumis asuvad objektid võivad ka ise nimeruumi kandjaks olla. NIMERUUM.VIDINAD = {}; NIMERUUM.vidinad.alert = function(tekst){ console.info(tekst); } NIMERUUM.VIDINAD.alert('test');

Nimeruumide korral ei saa funktsioone deklareerida kujul function NIMERUUM.funktsioon(){..}, vaid ainult läbi lambda avaldiste, kus anonüümne funktsioon omistatakse muutja väärtuseks NIMERUUM.funktsioon = function(){..}. Objekti kujul nimeruume saab kasutada ka dünaamiliselt. var nimeruum; if(a>b){ nimeruum = window; 97 / 109


JavaScript, Andris Reinman }else{ nimeruum = NIMERUUM; } nimeruum.alert(123);

või isegi nimeruumi nime stringina töödeldes var nimeruum = window['NIME' + 'RUUM']; nimeruum.alert(123);

98 / 109


JavaScript, Andris Reinman

15.

Bitioperatsioonid

Bitioperatsioonid on tegelikult tavalised numbritega opereerimised, ainsa erinevusega, et harjumuspärase kümnendsüsteemi asemel kasutatakse binaarseid numbreid. Kuna operatsioonide sisendid ja väljundid on reeglina siiski mitte binaar-, vaid kümnendkujul, võivad esmapilgul bitioperatsioonid paista üsna krüptilised ning ebaloogilised (12|5 = 13; 12^5 = 9 jne). Lahenduseks oleks operatsioonide ajaks unustada numbrite kümnendvormiline sisu ja vaadata kõike binaarselt. Sellisel juhul ebaloogilisus kaob ning võib selguda, et teatud juhtudel on bitioperatsioonid tegelikult üsnagi kasulikud. Kui teistes keeltes on bitioperatsioonid võrreldes muude operatsioonidega reeglina kiiremad, siis JavaScriptis paraku jäävad need suhteliselt aeglaseks. Bitioperatsioone kasutatakse tegelikult väga harva (kui üldse) ning peamiselt tekitavad nad ainult segadust. Probleemiks on bitioperaatorite operaatorid & ning |, mis on väga sarnased loogiliste operaatoritega && ning ||. Kui programmeerija teeb trükivea, kasutades loogilise operaatori asemel bitioperaatorit, siis sellest ei järgne veateadet programmi kompileerimisel ega käivitusel. Tulemuseks võib seega olla väga raskesti avastatav viga.

15.1.

32 bitised numbrid

Bitioperatsioonides teostatakse kõik operatsioonid 32 bitiste märgiga täisarvudega, kus vasakpoolseim bitt tähistab numbri märk (0: positiivne, 1: negatiivne). Kuna numbrid on JavaScriptis tegelikult topelttäpsusega 64 bitised reaalarvud, teisendatakse kasutatav number operatsiooni läbiviimiseks vastavalt 32 bitiseks. Vajadusel kustutates numbrist osad, mis lubatud 32 biti sisse ei mahu (näiteks numbri murdosa). Iga operatsiooniga kaasnev teisendus (sisendid ja väljundid on 64 bitised numbrid, operatsiooniks kasutatakse aga 32 bitist numbrit) asetab programmi täitmisel masinale paratamatult mõningase täiendava koormuse. Mõningatel juhtudel - näiteks lippude haldamisel vabaneva mälu arvelt - võib selle lisanduva koormusega siiski leppida. Pealegi, väiksemas mastaabis on tegu suhteliselt ebaolulise kaoga. Seega kuna numbreid käsitletakse binaarsüsteemis, tähendab see 32 kohalist jada mille liikmeteks võivad olla numbrid 0 ning 1. Näiteks numbrit 12 käsitletakse binaarsüsteemis kujul 1100 või õigemini 32 bitise numbrina 00000000000000000000000000001100

Kui me nüüd teostame selle numbriga mõne bitioperatsiooni, näiteks nihutame kõik bitid ühe sammu võrra paremale 12 >> 1

siis saame vastuseks numbri 6. Binaarkujul vaadates tähendab see 00000000000000000000000000000110

Ehk et nagu näha, ongi bitid liikunud ühe sammu võrra paremale. Kuna ruumi on täpselt 32 bitti, ei rohkem ega vähem, täidab operaator >> vasakule jäävad tühjad kohad märgibitiga (kõige vasakpoolsem bitt, mis näitab kas number on positiivne või negatiivne) ja kuna antud näites oli tegu positiivse arvuga, lisati vasakule null. Parempoolne üleliigne bitt kustutati operatsiooni käigus lihtsalt ära. 99 / 109


JavaScript, Andris Reinman

15.2.

Võrdlusoperatsioonid

15.2.1. Bitioperatsioon AND - & Operatsioon võrdleb kahe operandi bitte paaridena ning tagastab iga paari puhul väärtuse 1, kui mõlemad võrreldvad on seatud (1), vastasel korral tagastab väärtuse 0. 12 & 5

Vasak operand: 1100 // 12 Parem operand: 0101 // 5 ---Tulemus &: 0100 // 4

15.2.2. Bitioperatsioon OR - | Operatsioon tagastab bitipaaride puhul väärtuse 1, kui vähemalt üks operand on seatud (1), vastasel korral tagastab väärtuse 0. 12 | 5

Vasak operand: 1100 // 12 Parem operand: 0101 // 5 ---Tulemus |: 1101 // 13

15.2.3. Bitioperatsioon XOR - ^ Operatsioon tagastab bitipaari puhul väärtuse 1, kui võrreldavad bitid on erinevad. Vastasel korral on tagastusväärtuseks 0. 12 ^ 5

Vasak operand: 1100 // 12 Parem operand: 0101 // 5 ---Tulemus ^: 1001 // 9

15.2.4. Bitioperatsioon NOT - ~ NOT ~ on unaarne operatsioon kasutades vaid ühte operandi. Tagastusväärtuseks on operandi peegelpilt - juhul kui bitt on seatud, on vastav tagastusbitt 0 ning vastupidisel juhul 1. ~12

Operand

: 1100 // 12 100 / 109


JavaScript, Andris Reinman ---Tulemus ~: 0011 // 3

15.3.

Bittide nihked

15.3.1. Nihe vasakule - << Nihe vasakule liigutab kõik bitid operaatori parempoolse operandi väärtuse võrra vasakule. Bitid mis jäävad vasakult üle 32 biti piiri, kustutatakse. Paremale tekkivad tühjad kohad saavad väärtuseks nullid. 12 << 1

00000000000000000000000000001100 // 12 00000000000000000000000000011000 // 24

Joonis 1. Bittide nihe vasakule. MB - märgibitt 15.3.2. Nihe paremale - >> Nihe paremale liigutab kõik bitid operaatori parempoolse operandi väärtuse võrra vasakule. Paremalt üle jäävad bitid kustutatakse, vasakul täidetakse tühjad kohad märgibitiga. 12 >> 1

00000000000000000000000000001100 // 12 00000000000000000000000000000110 // 6

Joonis 2. Bittide nihe paremale. MB - märgibitt 15.3.3. Nulltäitega nihe paremale - >>> Nulltäitega nihe paremale liigutab kõik bitid operaatori parempoolse operandi väärtuse võrra vasakule. Paremalt üle jäävad bitid kustutatakse, vasakul täidetakse tühjad kohad nulliga. Positiivse arvu korral on tulemus sama, mis tavalise nihkega paremale. 12 >>> 1 101 / 109


JavaScript, Andris Reinman 00000000000000000000000000001100 // 12 00000000000000000000000000000110 // 6

Joonis 3. Nulltäitega nihe paremale. MB - märgibitt

15.4.

Lippude haldamine

Üheks heaks näiteks bitioperatsioonidel kasutamisel on liipude haldamine. Lipp on mingit olekut või sündmust tähistav muutuja, mida saab tähistada ühe bitiga. Kui bitil on väärtus 1, on lipp seatud. Ning vastupidi - kui bitil on väärtus 0, on lipp seadmata. Bittide kujul lippe hoida on otstarbekas peamiselt kahel põhjusel. Esiteks saaks lippu hoida mälus näiteks ka numbrina, kasutades väärtuseid 0 ja 1, kuid sellisel juhul kuluks lipu staatuse hoidmiseks ühe asemel tervelt 64 bitti. Loomulikult pole vahet, kui kasutuses on ainult üks lipp - aga erinevus tuleb sisse lippude kombineerimisel ühe 32 bitise numbri sisse. Teiseks kasulikuks omaduseks ongi just see lippude ühte kombineerimise võimalus. Sellisel juhul saab nende lippudega manipuleerida ühtse kogumina. Võimalik on kasutada operatsioonides bitimaske ning muuta nii korraga kõigi lippude olekuid ja positsioone numbri bitikohtades. 15.4.1. Erinevate bittide defineerimine Lippude arvestamise lihtsustamiseks tasub kõigepealt defineerida erinevate bittide olekud. var var var var var var var var var var var var var var var var var var var var var var var var var var var

BITT_1 BITT_2 BITT_3 BITT_4 BITT_5 BITT_6 BITT_7 BITT_8 BITT_9 BITT_10 BITT_11 BITT_12 BITT_13 BITT_14 BITT_15 BITT_16 BITT_17 BITT_18 BITT_19 BITT_20 BITT_21 BITT_22 BITT_23 BITT_24 BITT_25 BITT_26 BITT_27

= = = = = = = = = = = = = = = = = = = = = = = = = = =

0x1; // 0x2; // 0x4; // 0x8; // 0x10; // 0x20; // 0x40; // 0x80; // 0x100; 0x200; 0x400; 0x800; 0x1000; 0x2000; 0x4000; 0x8000; 0x10000; 0x20000; 0x40000; 0x80000; 0x100000; 0x200000; 0x400000; 0x800000; 0x1000000; 0x2000000; 0x4000000;

000001 000010 000100 001000 010000 100000 ... ...

102 / 109


JavaScript, Andris Reinman var var var var var

BITT_28 BITT_29 BITT_30 BITT_31 BITT_32

= = = = =

0x8000000; 0x10000000; 0x20000000; 0x40000000; 0x80000000;

15.4.2. Lippude seadmine Lippe saab seada bitioperaatoriga OR (|). Sellisel juhul jäävad puutumata kõik teised bitid v.a. bitt, mida tahetakse seada. Juhul kui bitt on juba olemas, jääb kõik samaks. Juhul kui aga pole, saab bitt väärtuse 1. var lipud = 0; lipud |= BITT_1; //Seame lipu nr 1 lipud |= BITT_4; //Seame lipu nr 4 alert(lipud.toString(2)); // 1001

Korraga saab seada ka mitu bitti, kasutades selleks nn. bitimaski, mille saab samuti koostada kasutades bitioperaatorit OR. var lipud = 0; var bitimask = BITT_1 | BITT_2; lipud |= bitimask;

15.4.3. Lippude väärtuste lugemine Lipu väärtust on mugav lugeda bitioperaatoriga AND (&). Kui võrrelda numbrit ning kindlat bitti, siis juhul kui numbris on võrreldav bitt seatud, on vastuseks sama biti numbriline väärtus. Kui aga bitti pole, on vastuseks 0. if(lipud & BITT_3){ alert('Bitt 3 on seatud'); }else{ alert('Bitt 3 on seadmata'); }

Mitme biti väärtuse kontrollimine bitimaskiga: if(lipud & (BITT_1 | BITT_2 | BITT_3)){ alert('Bitid 1,2 ja 3 on seatud'); }else{ alert('Bitid ei ole seatud'); }

15.4.4. Lipu mahavõtmine Lippu saab maha võtta (lippu tähistava biti bäärtuseks saab 0) liites lippudele operaatoriga AND bitioperatsiooni tehte NOT lipu väärtusest. Sellega muudame esiteks muutuja soovitud bitiga vastupidiseks, nii et kõik nullid muutuvad ühtedeks ning soovitud kohal asuv bitt muutub nulliks. Kui nüüd võrdleme seda lippudega kasutades operaatorit AND, jäävad kõik teised lipud muutmata 103 / 109


JavaScript, Andris Reinman

(z & 1 = z), aga soovitud bitt muutub nulliks. lipud &= ~BITT_2; // eemaldame lippude hulgast biti 2

Korraga mitme lipu väärtuse mahavõtmine bitimkaski kasutades: lipud &= ~(BITT_1 | BITT_2 | BITT_3);

15.4.5. Lippude kasutamise näide Käesolevas näites kasutame lippe kolme sahtliga kappi kujutava objekti sahtlite haldamiseks. Juhul kui lisame sahtlisse midagi, märgime et sahtel on kasutuses. Juhul kui teeme selle tühjaks, eemaldame lipu. Samuti saame uurida, kas sahtel on juba kasutuses või mitte. var alumine_sahtel = 0x1; var keskmine_sahtel = 0x2; var ylemine_sahtel = 0x4; var kapp = { sahtlid: 0, sahtel_kasutusse: function(sahtel){ this.sahtlid |= sahtel; }, sahtel_tyhjaks: function(sahtel){ this.sahtlid &= ~sahtel; }, sahtli_info: function(sahtel){ if(this.sahtlid & sahtel){ alert('Sahtel on juba kasutuses!'); }else{ alert('Sahtel on tühi!'); }; } } kapp.sahtel_kasutusse(ylemine_sahtel | keskmine_sahtel | alumine_sahtel); kapp.sahtel_tyhjaks(alumine_sahtel | ylemine_sahtel); kapp.sahtli_info(alumine_sahtel);

Näites märgime esiteks kõik sahtlid täidetuks. Seejärel tühjendame alumise ning ülemise sahtli ja lõpuks kontrollime, mis seisus on alumine sahtel. Vastus on oodatult, et sahtel on tühi.

104 / 109


JavaScript, Andris Reinman

16.

Regulaaravaldised

Sarnaselt paljudele teistele programmeerimiskeeltele, sisaldab ka JavaScript regulaaravaldisi. Regulaaravaldis on string, mis kirjeldab või langeb kokku mingi stringide hulgaga vastavalt kindlatele süntaksireeglitele. Tegu on omamoodi mustriga, mida saab rakendada erinevatele tekstidele, kontrollimaks nende tekstide vastavust. Üks võimalik kasutusvaldkond on näiteks vormielementide sisu kontroll vormide täitmisel - kas e-posti väljale sisestatud string näeb ikka eposti aadressi moodi välja või kas soovitud kasutajanimi on piisavalt pikk ja sisaldab vaid lubatud sümboleid. Kõige selle jaoks ongi kasutada regulaaravaldised. JavaScriptis on regulaaravaldised esitatavad RegExp objektidena. Sellist objekti saab kasutada näiteks stringi meetodi match parameetrina. if ("tekst" .match(/ks/)){ alert('Leiti tekstiline vaste "ks"!'); }

16.1.

RegExp objekt

RegExp

objekti saab luua kahel viisil. Esiteks läbi RegExp konstruktori ning teiseks regulaaravalidise literaalina. Konstruktoriga luues on regulaaravaldise loomise süntaks järgmine: var re = new RegExp("muster","lipud");

Kus muster tähistab regulaaravaldisele vastavat mustrit ning lipud tähistavad erinevaid seadeid, millega mustri kontrollimisel arvestatakse. Näiteks võib olla selleks väike täht i, mis tähistab tähesuuruse ignoreerimist. Regulaaravaldise literaaliks on sarnaselt teistele keeltele kaldkriipsud. var re = /muster/lipud;

NB! Kummagi süntaksi korral ei ole lippude määramine kohustuslik, lihtsamate avaldiste puhul võib need vajadusel ära jätta.

16.2.

Regulaaravaldise lipud

16.2.1. g - globaalne vaste Lipu g kasutamisel, tagastab regulaaravaldis kõik vasted, vastasel juhul aga ainult esimese. console.log("tekskskst" .match(/ks/g)); // ["ks", "ks", "ks"]

16.2.2. i - ignoreeri tähesuurust Kui regulaaravaldis kasutab lippu i, ei arvestata teksti kontrollil tähesuurust. console.log("tekskskst" .match(/KS/i)); // ["ks"] 105 / 109


JavaScript, Andris Reinman

16.2.3. m - mitu rida Regulaaravaldis arvestab rea alguse ja lõpu märgistuse sümboleid (^ ning $) mitte string alguse ja lõpu juures, vaid iga rea korral eraldi. "abc\ndef\nghi".match(/^def$/m); // ["def"]

16.3.

Erimärgid regulaaravaldises

Regulaaravaldises saab kasutada mitmeid erimärke, mis aitavadki moodustada nn. mustri. Näiteks sümbol ^, mis tähistab stringi algust (või rea algust, kui on kasutatud lippu m). Sümbol \

^ $ * + ?

. (z)

(?:z) x(?=y)

x(?!y) x|y {n} {n,} {n,m} [abc] [^abc]

[\b]

Selgitus Erimärk \ on kasutusel sarnaselt stringide defneerimisel erisümbolite muutmisel nende märgilisele kujule. Näiteks juhul kui otsime stringist märki ^, siis ei saa seda kirjutada kujul /^/, kuna see tähistaks ^ asemel hoopis rea algust. Sama süboli koos erimärgiga \ esitamisel otsitakse aga sümbolit tema tekstilisel kujul /\^/. Erimärk tähistab stringi algust. Juhul kui kasutusel on lipp m, tähistab see ka üksikute ridade algust stringis. Sellele sümbolile järgnev peab asuma stringi alguses. Erimärk tähistab stringi lõppu. Juhul kui kasutusel on lipp m, tähistab see ka üksikute ridade lõppu stringis. Sellele sümbolile eelnev peab asuma stringi lõpus. * vastab eelnenud elemendile 0 või rohkem kordi. Näiteks /abc*/ vastab stringile „abc“ ning „abccccc“. Erimärk + vastab eelnenud elemendile 1 või rohkem kordi. ? vastab eelnenud elemendile 0 või 1 korra. /abc?/ vastab nii stringile klaabu kui ka abcdef. Juhul kui erimärki ? kasutatakse peale erimärke *, +, ? või {}, muudab ? sunnib antud märke kaasama vasteks minimaalse võimaliku arvu sümboleid. Vaikimisi üritatakse haarata tekstist võimalikult suur arv sümboleid. . (punkt) vastab suvalisele sümbolile, välja arvatud reavahetuse märkidele \n ja \r Sulud märgivad ära soovitud mustrile z vastava tekstiosa ning jätavad selle meelde. Kasulik on see näiteks mingi teadmata pikkusega teksti leidmiseks kindlast asukohast nagu HTML koodis linkide aadressid. /href="(.*?)"/g Sarnaselt tavalistele sulgudele, otsitakse mustrile z vastavaid tekstiosi, kuid tulemusi ei jäeta meelde. Mustrit x arvestatakse ainult juhul, kui sellele järgneb muster y. /Jaan(?=Tamm)/ vastab tekstile „Jaan“ ainult juhul, kui sellele järgneb vahetult „Tamm“. Sulgudes olevat osa ei tagastata tulemusena. Mustrit x arvestatakse ainult juhul, kui sellele ei järgne mustrit y. /Jaan(?!Tamm)/ vastab tekstile „Jaan“ ainult juhul, kui sellele ei järgne vahetult stringi „Tamm“. Vastab kas mustrile x või y Vastab täpselt n (positiivne täisarv) kordust eelnenud märgendi kohta. /a{5}/ vastab stringile „aaaaa“ Vastab vähemalt n (positiivne täisarv) kordust eelnenud märgendi kohta. /a{,5}/ vastab stringile „aaaaaaaa“ (rohkem kui 5 kordust) Vastab vähemalt n, kuid mitte rohkem kui m (positiivsed täisarvud) kordust eelnenud märgendi kohta. /a{5,7}/ vastab stringile „aaaaaa“ Tähevalik, otsing peab vastama vähemalt ühele nimekirjas olevale sümbolile. Sümbolijadade kaasamiseks võib kasutada miinusmärki ([0-9] on sama mis [0123456789]) Negatiivne tähevalik, otsing ei tohi vastata ühelegi nimekirjas olevale sümbolile. Sümbolijadade kaasamiseks võib kasutada miinusmärki ([^0-9] on sama mis [^0123456789]) Tähistab tagasilükke sümbolit 106 / 109


JavaScript, Andris Reinman \b \B \cX \d \D \n \r \s \S \t \w \W \z \0 \xHH \xHHHH

Tähistab sõna serva. /\bk/ vastab tähele k stringis katus Tähistab serva puudumist. /\bt/ vastab tähele t stringis katus X tähistab tähevahemikku A-Z. Tegun on kontrollsümboliga, \cA tähistab Ctrl+A sümbolit tekstis. Tähistab numbrit vahemikus 0-9 Tähistab sümboleid, mis pole numbrid, sama mis [^0-9] Tähistab reavahetuse sümbolit \n Tähistab tagastussümbolit \r Tähistab tühemiku sümbolit - tühik, reavahetus jms Tähistab sümbolit, mis ei esita tühemikku Tähistab tabulatsioonisümbolit \t Tähistab suvalist tähelis-numbrilist sümbolit, kaasa arvatud alakriipsu ([a-zA-Z0-9_]) Tähistab suvalist sümbolit, mis pole täheline-numbriline, sh. alakriips ([^a-zA-Z0-9_]) z on positiivne täisnumber. Erisümbol tähistab z kordset tagasiviidet eelnevalt sulgudega määratud (vasakult lugedes) sisu juurde Tähistab erisümbolit NUL Tähistab kuueteistkümnendsüsteemis määratud koodiga sümbolit. Tähistab kuueteistkümnendsüsteemis määratud kahekordse koodiga Unikood sümbolit.

Tabel 4. Erimärgid regulaaravaldistes Regulaaravaldised on üldiselt üsnagi võimekad ning siinsest ruumist ei piisa nende täielikuks lahtikirjutamiseks. Täpsemat infot tasub otsida regulaaravaldistele keskendunud raamatutest. Kuna JavaScripti regulaaravaldised on modelleeritud programmeerimiskeele PERL vastava väga levinud süntaksi alusel, ei tohiks materjali leidmisega probleeme tekkida.

107 / 109


JavaScript, Andris Reinman

17.

Erindid

Erind (exception) on märguanne, mis teatab erijuhu või vea tekimisest ning üldjuhul tähendab see mingisugust tõrkeolukorda. Käsuga throw saab tekitada uue erindi ning lausega catch saab selle kinni püüda. Kui erind ei ole kontrollitud (tekib väljaspool try blokki), peatab see terve programmi edasise töö.

17.1.

throw

throw

tekitab veaobjekti ning lõpetab sellega programmi töö täitmise. Juhul kui throw asub try blokis, lõpetatakse bloki töö ja edastatakse veaobjekt catch blokile (juhul kui on seatud) ilma programmi enda täitmist segamata. throw new ReferenceError("Muutuja on seadmata!");

try{ throw new Error("Ilmnes viga!"); }catch(err){ alert(err.message); // Ilmnes viga! }

17.2.

Error

Veatüüpe on erinevaid - Error, EvalError, RangeError, ReferenceError, SyntaxError, TypeError. Sisuliselt on tegemist sarnaste objektidega, välja arvatud objekti omadus name, mis on võrdne vea tüübi nimega. Näiteks SyntaxError veaobjekti name omaduse väärtus on "SyntaxError" ning RangeError objekti name omaduse väärtus on "RangeError". See eristumine on vajalik catch blokis vea põhjuse määramiseks. try{

abc; //ReferenceError }catch(E){ alert('Ilmus '+E.name+' tüüpi viga!'); }

Veaobjekti deklareerimine: new Error([teade [,failiNimi [,reaNumber]]);

ning reeglina käib see käskluse throw juurde. Veaobjekt koosneb järgmistest elementidest: • name - tähistab vea tüüpi stringi kujul ("Error", "ReferenceError" jne) • message - vabas vormis tekst selgitusega vea tekkimise kohta (selleks saab veaobjekti luues new Error(msg); parameeter msg)

108 / 109


JavaScript, Andris Reinman

• fileName - faili URL, milles viga tekkis • lineNumber - rida programmis, kus viga tekkis Veatüüpidest saab täpsemalt lugeda globaalsete objektide peatükist.

17.3.

try/catch/finally

try

blokk võimaldab „proovida“ soovitud käsklusi. Kui blokis peaks ilmnema mingi viga, ei lõpetata programmi tööd, vaid antakse info vea kohta edasi blokile catch. Lõpuks (hoolimata vea tekkimisest/mittetekkimisest) antakse järg üle blokile finally. catch ja finally blokid pole struktuuris kohustuslikud, kuid vähemalt üks neist peab try blokile järgnema. try{

// proovime mingeid käsklusi }catch(err){ // käivitub kui try blokis oli viga }finally{ // käivitub igal juhul } catch

blokile edastatav parameeter err on Error objekt, mis sisaldab endas tekstikujulist selgitust vea ilmnemise ning vea tüübi kohta.

17.4.

onError sündmus

Brauseris käivitatava JavaScripti puhul on võimalik kasutada onError sündmuse seadmist. Sellisel juhul suunatakse kõik erindid sellele sündmuse juhtijale. window.onerror = function(err, url, code){ // err - veaobjekt // url - fail, milles viga ilmnes // code - rea number return true; }

Juhul kui sündmust haldav funktsioon tagastab tõese väärtuse (true), jätkab programm tööd, vastupidisel juhul töö lõpetatakse. Juhul kui onError sündmus seatakse HTML koodis <body onerror = "alert('ilmnes viga!');...">

saab eelpool näidatud parameetritele err, url ja code ligi arguments objektiga (arguments[0], arguments[1] ja arguments[2]). Sündmusega onError erindeid kinni püüda pole siiski eriti soovituslik. Mõistlikum oleks kasutada try/catch blokke, sellisel juhul oleks pikemas programmis viga tunduvalt kergem lokaliseerida ja hallata.

109 / 109


Turn static files into dynamic content formats.

Create a flipbook
Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.