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 - x²/2 + x³/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 ...

results matching ""

    No results matching ""