JS: Anonüümsed funktsioonid – Noolefunktsioonid

JavaScriptis on funktsioone võimalik luua ja kasutada mitmel erineval viisil. Üks levinumaid meetodeid on klassikalised funktsioonid, mida käsitlesime eelmises peatükis. Need on nimelised funktsioonid, mis võivad vastu võtta argumente, sisaldada käskude kogumit (keha) ja tagastada väärtusi. Klassikalisi funktsioone kasutatakse kindlate ülesannete täitmiseks või arvutuste tegemiseks.

Lisaks neile on JavaScriptis olemas ka muud funktsioonitüübid, näiteks anonüümsed funktsioonid ning nende uuem versioon – noolefunktsioonid.

Anonüümsed funktsioonid

Anonüümsed funktsioonid on funktsioonid, millel ei ole nime ja mis luuakse otse koodi sisse seal, kus neid vaja on. Tavaliselt kasutatakse neid siis, kui funktsiooni on vaja vaid ühekordselt või lokaalselt – näiteks muutujasse salvestamiseks, teise funktsiooni argumendina või objekti atribuudina. Pärast määratlemist lõpetatakse funktsioon semikooloniga “;“.

Näide anonüümsest funktsioonist:

var tervita = function() 
{
  console.log("Tere maailm!");
};

tervita();

Näide anonüümsest funktsioonist argumentidega:

var summa = function(a, b) 
{
  return a + b;
};

var tulemus = summa(3, 5);
console.log(tulemus); // Väljund: 8

Anonüümseid funktsioone kasutatakse sageli ka teistele funktsioonidele argumentidena – näiteks sündmuste käsitlemisel või viivituste määramisel:

setTimeout(function() 
{
  console.log("Tere pärastlõunast!");
}, 1000);

Neid saab kasutada ka massiivide elementide läbikäimiseks, näiteks forEach meetodiga:

var array = [1, 2, 3, 4, 5];

array.forEach(function(element) 
{
  console.log(element);
});

Võimalik on kasutada ka täiendavaid parameetreid nagu elementide indeks või kogu massiiv:

const array = [1, 2, 3, 4, 5];

array.forEach(function(element, index, array) 
{
  console.log("Element:", element);
  console.log("Index:", index);
  console.log("Array:", array);
});

Eelised ja kasutusvaldkonnad:

Anonüümsed funktsioonid pakuvad paindlikkust ja lihtsust, olles eriti kasulikud väikeste ja ühekordsete tegevuste jaoks. Need on olulised sündmustepõhises ja asünkroonses programmeerimises.

Klassikalised (nimelised) funktsioonid seevastu sobivad paremini korduvaks kasutamiseks ja keerukamateks operatsioonideks, näiteks rekursiooniks või objektorienteeritud programmeerimiseks.

Kokkuvõttes täiendavad mõlemad lähenemised teineteist – anonüümsed funktsioonid on mugavad lühikesteks toiminguteks, samas kui klassikalised funktsioonid tagavad koodi parema struktuuri ja taaskasutatavuse.

IIFE (Immediately Invoked Function Expression)

IIFE (Immediately Invoked Function Expression) on anonüümse funktsiooni erivorm. Selle nimi tuleneb asjaolust, et funktsioon kutsutakse kohe pärast selle defineerimist välja.

IIFE koosneb sulgudesse pandud anonüümsest funktsioonist, mis käivitatakse viivitamatult, lisades selle järele veel ühe paari sulge.

IIFE eristub teistest anonüümsetest funktsioonidest selle poolest, et seda käivitatakse kohe samal hetkel, kui see luuakse – erinevalt tavalistest anonüümsetest funktsioonidest, mida lihtsalt defineeritakse, kuid ei kutsuta kohe välja.

(function() 
{
  var x = 10;
  console.log(x); // Output: 10
})();

Noolefunktsioonid

ES6 standardi kasutuselevõtuga toodi JavaScripti uus viis anonüümsete funktsioonide loomiseks – noolefunktsioonid (arrow functions). Tegemist on anonüümsete funktsioonide erivormiga, mille süntaks on lihtsam ja kompaktsem. Noolefunktsioon kasutab funktsioonikeha määratlemiseks nooleoperaatorit (=>).

Noolefunktsioonide peamised eelised on lühem ja selgem süntaks ning automaatselt seotud this väärtus väliskontekstiga. Tänu sellele saab kirjutada anonüümseid funktsioone lühemalt ja kergemini loetaval kujul.

Näide noolefunktsioonist:

const noolFunktsioon= () => 
{
  // funktsiooni keha
};

Ehk lihtne tervitus näeks välja järgmine

const noolFunktsioon = () => 
{
  console.log("Tere noolfunktsioon!")
};

noolFunktsioon();

Kui funktsiooni kehas on ainult üks avaldus, siis saame isegi loogelised sulud {} ära jätta.

const noolFunktsioon = () => console.log("Tere noolfunktsioon!");
noolFunktsioon();

Ja argumentidega ja massiiviga funktsiooni näited

//noolefunktsioon argumentidega
let tervita = (nimi) => {console.log(`Tere ${nimi}`)};
tervita("Juhan");

//noolefunktsioon lihtsustatud - KUI ARGUMENTE ON ÜKS, SIIS VÕIB KA NEED SULUD ÄRA JÄTTA
let tervita2 = nimi => console.log(`Tere ${nimi}`);
tervita2("Mari");

//kui kehas on rohkem ridu, siis sulud jäävad
let liitmine = (a, b) => 
{
  let result = a + b;
  return result;
};
console.log(liitmine(3,5));

//noolefunktsioon lihtsustatud argumentidega
let liitmine2 = (a, b) => a + b;
console.log(liitmine2(3,5));

//noolefunktsioon ja massiviist elementide kuvamine
const array = [1, 2, 3, 4, 5];
array.forEach(element => console.log(element));

Eriti läheb huvitavamaks, kui lisada mitu lühendatud koodi kokku. Näiteks funktsioon, mis leiab kas arv on paaris või paaritu

const number = 5;
const isEven = number => number % 2 === 0 ? "paaris" : "paaritu";

console.log(isEven(number)); // Väljund: paaritu

Ja sama näide massiivi korral

const arvud = [1, 2, 3, 4, 5];

arvud.forEach(nr => 
{
  const paaris = nr % 2 === 0 ? "paaris" : "paaritu";
  console.log(`${nr} is ${paaris}`);
});

Noolefunktsioone ei sobi kasutada järgmistes olukordades:

  1. Konstruktorifunktsioonides – noolefunktsioonidel puudub oma this sidumine, seega ei saa neid kasutada objektide loomiseks konstruktorite kaudu. Konstruktorid vajavad this viidet, et määrata uue objekti omadusi.
  2. Objekti meetoditena – kui meetod peab kasutama objekti enda this väärtust, ei sobi noolefunktsioon. Noolefunktsioon pärib this väärtuse ümbritsevast kontekstist, mitte objekti enda kontekstist.
  3. Prototüüpimeetoditena – kui lisada prototüübile meetod noolefunktsioonina, ei saa this õigesti viidata objektile, mille meetodit kutsutakse. See tähendab, et prototüübi meetodid ei tööta ootuspäraselt.

Tagasikutsumisfunktsioonid (Callbacks)

Tagasikutsumisfunktsioonid on JavaScriptis meetod, kuidas ühte funktsiooni saab teisele edastada ning hiljem selle tagasi kutsuda. See võimaldab teatud sündmuste või tingimuste täitumisel sooritada soovitud toiminguid.

Võib seda võrrelda “helistamise ja tagasihelistamise” süsteemiga: sa helistad kellelegi ja palud neil midagi teha ning hiljem helistavad nemad sulle tagasi, et anda teada, et ülesanne on lõpetatud. Tagasikutsumisfunktsioonid toimivad samamoodi.

Näiteks kasutamegi seda sageli forEach meetodis. forEach võtab argumendiks callback-funktsiooni ja kutsub seda iga massiivi elemendi puhul eraldi.

let nimed = ["Kati", "Marta", "Andres", "Jüri", "Liisa"];

nimed.forEach(function(nimi) 
{
  console.log(`<li>${nimi}</li>`);
});

Võime funktsiooni ka eraldi luua ja siis selle välja kutsuda.

let nimed = ["Kati", "Marta", "Andres", "Jüri", "Liisa"];

const kasutaja = function(nimi) 
{
  console.log(`<li>${nimi}</li>`);
};

nimed.forEach(kasutaja);

Ja veel parem, me saame selle panne kirja noolefunktsioonina

let nimed = ["Kati", "Marta", "Andres", "Jüri", "Liisa"];

//pikalt
const kasutaja = nimi => console.log(`<li>${nimi}</li>`);
nimed.forEach(kasutaja);

//lühidalt
nimed.forEach(nimi => console.log(`<li>${nimi}</li>`));

Näide lihtsast AJAX API päringust koos callback-funktsiooniga, kasutades noolefunktsiooni

const teostaAJAXPäring = (url, callback) => 
{
  setTimeout(() => {
    const vastus = "Vastus andmebaasist";
    callback(vastus);
  }, 2000);
};

const callbackFunktsioon = (vastus) => 
{
  console.log("Vastus saadud:", vastus);
};

teostaAJAXPäring("https://api.example.com/data", callbackFunktsioon);

Ülesanne 

1. Erinevad funktsioonid:

Koosta kaks funktsiooni, mis väljastavad sinu nime (ilma ühegi argumendita). Kasuta klassikaslist ja noolefunktsioone.

Normaalne funktsioon:

function minuNimi() 
{
    console.log("Nikita Litvinenko");
}

minuNimi();

Noolefunktsioon:

const minuNimi = () => { console.log("Nikita Litvinenko"); }
minuNimi ();

2. Argumendiga funktsioon

Kirjuta funktsioon nimega `kuupaevEesti`, mis kuvab konsoolile praeguse kuupäeva ja kuu eesti keeles. Argumendiks kuupäev kujul 19.07.25

const kuuNimed = [
	"jaanuar", "veebruar", 
	"märts", "aprill", "mai", 
	"juuni", "juuli", "august", 
	"september", "oktoober", "november", 
	"detsember"
];

function kuupaevEesti(kuupaev) 
{
    const split = kuupaev.split(".");
	const paev = split[0];
	const kuu = split[1];
	const aasta = split[2];

    const kuuNimi = kuuNimed[kuu - 1];

	console.log(`${paev}. ${kuuNimi} ${"20" + aasta}`);
}

kuupaevEesti("19.07.25");

3. Teadmata hulk

Kirjuta funktsioon, mis võtab siseniks kasutajalt teadmata hulga täisarve ning tagastab nende koguarvu ning keskmise.

function KeskmineJaSumma(numbrid)
{
	let sum = 0;
	
	for (let i = 0; i < numbrid.length; i++) 
		sum = sum + numbrid[i];

	let keskmine = sum / numbrid.length;

	return [sum, keskmine]
}

const tulemus = KeskmineJaSumma([5, 5, 2]);
const sum = tulemus[0];
const keskmine = tulemus[1];
console.log('Summa: ' + sum + ' Keskmine: ' + keskmine);

4. Salajane sõnum

Kirjuta noolefunktsioon nimega salajaneSonum, mis võtab sisendiks sõnumi stringi ning tagastab selle sõnumi põhjal salajase versiooni. Salajase versiooni loomiseks asendatakse kõik täishäälikud (vokaalid) tärniga (*), jättes konsonandid muutumatuks.

const salajaneSonum = (tekst) => 
{
	let tulemus = "";
 
	for (let i = 0; i < tekst.length; i++) 
	{
		let taht = tekst[i];

		if (taht === "e" || taht === "u" || taht === "o" 
		|| taht === "ü" || taht === "õ" ||  taht === "a" 
		|| taht === "ö" || taht === "ä" || taht === "i") 
			tulemus += "*";
		else 
			tulemus += taht;
	}
 
	return tulemus;
};
 
console.log(salajaneSonum("Tere päevast!"));

5. Unikaalsed nimed

Kirjuta noolefunktsioon nimega leiaUnikaalsedNimed, mis võtab sisendiks massiivi erinevatest nimedest ning tagastab uue massiivi, kus on ainult unikaalsed nimed esialgses järjekorras. See tähendab, et kui esineb mitu sama nime, siis tuleb need jätta ainult esinemise esialgsesse kohta ja eemaldada ülejäänud koopiad.

const leiaUnikaalsedNimed = (nimed) => 
{
	const tulemus = [];
	let num = 0;

	for (const nimi of nimed) 
	{
		let on = false;

		for (let i = 0; i < tulemus.length; i++) 
		{
			if (tulemus[i] === nimi) 
				on = true;
		}
		
		if (!on) 
		{
			tulemus[num] = nimi;
			num = num + 1;
		}
	}

	return tulemus;
};

console.log(leiaUnikaalsedNimed(["Kati", "Mati", "Kati", "Mari", "Mati", "Jüri"]));