Funksjoner

En funksjon er en samling av kode inne i et større program som utfører en spesifikk oppgave og er relativt uavhengig av resten av koden.

En funksjon oppfører seg på mye av den samme måten som et vanlig program - men den er ofte kodet slik at den kan brukes flere ganger mens hovedprogrammet kjører. Funksjoner er viktige verktøy i programmering og kan bidra til å strukturere programmer på en god måte.

Objektorientert programmering går som regel ut på å binde sammen funksjoner og data på en logisk måte, et elev-objekt har funksjoner for å skrive ut elevdata osv.

Mange språk har samlinger av funksjoner i funksjonsbibliotek eller klasser (tenk på Math i actionscript).

Ofte er det nødvendig å sende verdier inn til funksjonene, disse verdiene kalles for parametre eller argumenter til funksjonen.

Et eksempel på dette er sinus funksjonen.

var x = 1.2;
var y = sin(x);

Her er x en parameter som brukes av funksjonen sin til å beregne en verdi (som lagres i variabelen y).

Mange funksjoner sender tilbake resultatet av en beregning - det gjøres med kommandoen return. Se eksemplene under for bruk av return. Dersom du ikke angir noen return verdi, da vil funksjonen returnere verdien undefined. I javascript kan du bare returnere én verdi, men den kan være en av alle definerte typer/klasser.

Definere funksjoner

Du definerer en funksjon på følgende måte:

function navnPaaFunksjon(parameter1, p2) {
// den neste linja er vanlig
var r; // verdien som skal returneres
// programkode
// en eller flere linjer, løkker, betingelser osv
// som oftest gir funksjonen en verdi tilbake
return r;
}

Som et eksempel viser vi definisjonen av sin():

function sin(x) {
var y; // verdien som skal returneres
// vi bruker en Taylor approximasjon
// dette er ikke den reelle definisjonen av Math.sin
y = x - x*x*x/(3*2) + x*x*x*x*x/(5*4*3*2);
return y;
}

Når funksjonen er definert, kan vi bruke den i kode:

var x = 0.7657;
var y = sin(x);
console.log(y);
// skriver ut 0.693..

Merk at parantesene etter navnet på funksjonen beskriver hvilke data du skal sende til funksjonen.

Definisjonen:

/**
* @param {number} x
* @returns {number} tilnærma verdi for sinus til x
*/
function sin(x) {}

sier at sin skal ta imot et Number og beregner en ny verdi av typen Number som returneres.

Denne måten å dokumentere en funksjon på er basert på jsdoc.

Anonyme funksjoner og arrow funksjoner

Du kan også lage funksjoner som ikke blir tildelt et navn.

btnBeregn.addEventListener("click", function(e) {
// utfør beregning
})

Denne typen kalles anonyme funksjoner og kan også brukes til å kjøre kode med en gang uten å ta vare på funksjonen. Den kan dermed ikke kjøres omigjen ved et uhell (da den ikke lenger finnes).

function() {
let a = 12; // denne forsvinner etter funksjonen er ferdig
// mer kode som kjøres ved oppstart
}();

Merk de to parantesene til slutt () . De vil aktivere den anonyme funksjonen og kjører koden, deretter er funksjonen borte. Dette kan være nyttig ved oppstart av et spill/app.

Arrow funksjoner

En arrow funksjon defineres slik:

let f = e => e + 1;
// f(2) === 3
let skalar = (u,v) => u.x * v.x * + u.y * v.y + u.z * v.z;
let kryss = (u,v) => [u.y * v.z - u.z * v.y , u.z * v.x - u.x * v.z , u.x * v.y - u.y * v.x];
let sin = x => { return x -/2 +/6;}
let cos = (x) => { return Math.cos(x); }

Merk at du trenger paranteser rundt parameterlista dersom den er tom eller har fler enn 1 parameter. Dersom funksjonskroppen bare er et uttrykk - da slipper du skrive return eksplisitt. Dersom du bruker { } rundt kroppen - da må du skrive return for å gi tilbake en verdi.

( ) => 12; // en arrow func uten parameter, returnerer 12 som verdi
x => x * x; // bare en parameter, slipper parantes
(x) => x*x+2; // du kan bruke parantes dersom du ønsker det selv med 1 parameter
(x,y) => x*x + y*y; // her må du ha paranteser
(a,b) => { return a+b;} // når du bruker { } rundt kroppen MÅ du skrive return

Den er en forenkla skrivemåte for anonyme funksjoner (med en del endra egenskaper).

btnBeregn.addEventListener("click", e => { /* kode */ } );
// tillsvarer den anonyme funksjonen for btnBeregn vist tidligere
tall.sort( (x,y) => x - y );
// merk at du ikke trenger return dersom du ikke bruker {} rundt funksjoneskroppen
// tillsvarer tall.sort(function(x,y) { return x - y;})

Arrow funksjoner binder ikke this. Dermed vil this være definert av scopet hvor arrow funksjonen defineres. Dette er ofte ønskelig for eksempler som under:

class Person {
constructor(age) {
this.age = age;
setInterval( () => this.age++,1000);
// i arrow funksjonen vil this være Person sin this
}
}
var p = new Person(0);
p.age; // 12
p.age; // 16 -- alder øker med 1 for hvert sekund

Uten arrow funksjon er dette ikke så rett fram

this.age = 100; // den globale this får egenskapen age
class Menneske {
constructor(age) {
this.age = age;
setInterval( function() {this.age++;},1000);
// den globale this.age øker for hvert sekund
}
}
var m = new menneske(40);
m.age; // 40
m.age; // 40 .. m.age endrer seg ikke
this.age; // 156 ... this.age øker for hvert sekund

Her vil funksjonen i setIntervall bruke en this som er kobla til det globale skopet Dermed vil m.age ikke endres.

Bruke funksjoner

Dersom du har definert en funksjon selv eller ønsker å bruke en som er ferdig definert i javascript, så er metoden den samme:

navnetPaaFunksjonen();

Du kjører koden som funksjonen representerer (kroppen til funksjonen) ved å nevne den ved navn - etterfulgt av ().

Dersom funksjonen tar parametre sendes disse i parentesene etter funksjonsnavnet - slik som sinus-funksjonen:

var y = sin(1.23);

Verdien du sender kan være et tall (slik som over) eller en variabel. Dersom du bruker en variabel, da hentes verdien ut og sendes til funksjonen - som om du hadde skrevet det tallet som er lagra i variabelen.

var x = 1.23;
var y = sin(x); // tilsvarer sin(1.23)

Dette har samme effekt som om du skrev y = sin(1.23) siden x inneholder tallet 1.23.

Avanserte funksjoner

Funksjoner av høyere orden er vanligvis betegnelsen på funksjoner som tar funksjoner som parameter, eller gir tilbake funksjoner som return-verdi.

Vi skal ikke dykke dypt her, men gi en liten innføring.
Dette temaet kan du lese mer om på nett dersom du søker på functional programming javascript.

Gjennomgang av alle elementer i en array.

Ofte lager vi kode som under for å gå gjennom elementene i en tabell (array).

// anta var elever er en array
for (var i = 0; i < elever.length; i++) {
// vi gjør noe med elementet elever[i]
// f.eks vi kjører en funksjon på elementet
sendBrev(elever[i]); // sender email til valgt elev
}

Det hadde vært nyttig om vi kunne si

ta denne funksjonen (sendBrev) og bruk den på
alle elementer i elever

Vi kan lage en slik funksjon:

function forAlle(arr, handling) {
for (var i = 0; i < arr.length; i++) {
handling( arr[i] );
}
}
// eksempel på bruk
forAlle( elever, sendBrev );

Alle elementer i en tabell skal endres

Tenk deg at du har en tabell som inneholder priser for en webshop. Nå har det blitt nødvendig å skru opp prisene med 5%.

// anta var priser er en array
for (var i = 0; i < priser.length; i++) {
priser[i] *= 1.05; // legger til 5%
}

Vi lager en funksjon som kan endre verdiene i en tabell:

function endreAlle(arr, endring) {
for (var i = 0; i < arr.length; i++) {
arr[i] = endring( arr[i] );
}
}
// eksempel på bruk
function prisVekst(pris) { return pris*1.05; }
endreAlle(priser, prisVekst);

Innebygde array-funksjoner

De to eksemplene vi har vist er allerede ferdiglaga for array i javascript.

elever.forEach(sendBrev);
var nyePriser = priser.map(prisVekst);
// merk at map lager en ny array
// endreAlle funksjonen vi laga over endrer originalen

I tillegg finnes

.reduce .reduceRight .each .filter .every .some

som er mer avanserte høyere ordens funksjoner. Sjekk dem ut på google ...

Last updated on