Andrise programmeerimisalane WIKI

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.

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 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.

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.

|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).

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.

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.

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.

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;

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.

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]

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"];
puuviljad.join(); // banaan,õun,pirn
puuviljad.join(", "); // banaan, õun, pirn
puuviljad.join(" | "); // banaan | õun | pirn

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]

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.

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]

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]

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"}]

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]
m.sort(function(a,b){
    return 0.5 - Math.random();
});
alert(m);

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.

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]