FJS26 · V46 · ONSDAG

Modern JavaScript
och funktionell
stil

Igår gömde vi datan i objekt. Idag låter vi den flöda genom funktioner.

Chas Academy · Onsdag 11 november 2026


Idag

01Uppvärmning02Vad är funktionell stil?03Closures04Kassan05När passar vad?06Efter passet
MODERN JAVASCRIPT OCH FUNKTIONELL STIL2 / 32
”

Igår svarade OOP på frågan var bor datan, och vem får ändra den? Idag är det den funktionella stilens tur.

01

Uppvärmning

Det här kan ni redan. Gissa först.

UPPVÄRMNING


Vad loggas?

Gissa först. Får vi något nytt, eller ändrar vi originalet?

1

const a = { x: 1, y: 2 };
const b = { ...a, y: 3 };

console.log(a.y, b.y);

2

const prices = [59, 35];
const lower =
  prices.map((p) => p - 10);

console.log(prices, lower);

3

const items =
  ['kaffe', 'bulle'];
const same = items;
same.push('te');

console.log(items.length);
MODERN JAVASCRIPT OCH FUNKTIONELL STIL5 / 32
02

Vad är
funktionell stil?

Funktionell programmering

Ett paradigm där programmet byggs av funktioner som tar in data och returnerar ny data, i stället för att ändra den som finns.

  • Rena funktioner: samma indata ger samma utdata, utan sidoeffekter.
  • Immutability: skapa nytt i stället för att ändra.
  • Funktioner är värden: de kan skickas in och returneras.
  • Deklarativt: beskriv vad du vill ha, inte hur steg för steg.
MODERN JAVASCRIPT OCH FUNKTIONELL STIL7 / 32

FUNKTIONELL STIL


Ren eller oren?

Ren funktionbara indata in, bara ett värde uttotal(items)items119samma items, samma svar,varje gångOren funktionläser och ändrar saker utanför sig självcheckout()let totalproductsconsoleDOMMath.random()
MODERN JAVASCRIPT OCH FUNKTIONELL STIL8 / 32

FUNKTIONELL STIL


Sidoeffekter

Allt en funktion gör utöver att returnera ett värde.

Ändrar

Muterar indata (push, sort), ändrar en global variabel, skriver till localStorage.

Pratar med omvärlden

console.log, rör DOM:en, fetch.

Beror på omvärlden

Math.random(), new Date(), läser en global som kan ändras. Inte en sidoeffekt i sig, men gör funktionen oren.

MODERN JAVASCRIPT OCH FUNKTIONELL STIL9 / 32

Övning

Ren eller oren?

Öppna 2-ren-eller-oren/js/main.js. Skriv REN eller OREN ovanför var och en av de åtta funktionerna, och varför. Skriv sedan om två av de orena så att de blir rena.

Tid

10 min

Mål

Du kan avgöra om en funktion är ren, och göra en oren funktion ren genom att ta in det som ändras som parameter.

MODERN JAVASCRIPT OCH FUNKTIONELL STIL10 / 32
”

Målet är inte noll sidoeffekter. Ett program utan dem gör ingenting. Målet är att samla dem på få ställen.

FUNKTIONELL STIL


Rent i mitten, sidoeffekter i kanten

main.js: sidoeffekternaläsa från DOM:enfetchlocalStorageconsole.logrenderareceipt.js: rena funktionersubtotal()applyDiscount()vatOf()formatReceipt()data inny data
MODERN JAVASCRIPT OCH FUNKTIONELL STIL12 / 32

FUNKTIONELL STIL


Funktioner är värden

En higher-order function tar emot eller returnerar en funktion. Ni har skrivit dem sedan v44.

Tar emot en funktion

const isCheap = (item) => item.price < 40;

items.filter(isCheap);

Returnerar en funktion

const cheaperThan = (limit) =>
  (item) => item.price < limit;

items.filter(cheaperThan(40));
MODERN JAVASCRIPT OCH FUNKTIONELL STIL13 / 32

FUNKTIONELL STIL


Deklarativt mot imperativt

Namnen på drycker under 50 kr, sorterade.

Imperativt: hur

const names = [];
for (const item of items) {
  if (item.category === 'dryck'
      && item.price < 50) {
    names.push(item.name);
  }
}
names.sort();

Deklarativt: vad

const names = items
  .filter((i) => i.category === 'dryck')
  .filter((i) => i.price < 50)
  .map((i) => i.name)
  .sort();
MODERN JAVASCRIPT OCH FUNKTIONELL STIL14 / 32
03

Closures

Hur funktionell kod håller tillstånd utan klasser.

Closure

En funktion som minns variablerna i scopet där den skapades, även efter att den yttre funktionen har kört klart.

  • Bygger på scope-kedjan från förra veckan: en inre funktion ser variablerna i de yttre.
  • Det nya är att den fortsätter att se dem, så länge den själv finns kvar.
MODERN JAVASCRIPT OCH FUNKTIONELL STIL16 / 32

CLOSURES


En funktion som minns

Koden

const makeGreeter = (greeting) => {
  return (name) =>
    `${greeting}, ${name}!`;
};

const hej = makeGreeter('Hej');
const hello = makeGreeter('Hello');

Användningen

makeGreeter har kört klart. Ändå vet hej att greeting är 'Hej'.

hej('Ada');    // 'Hej, Ada!'
hello('Ada');  // 'Hello, Ada!'
MODERN JAVASCRIPT OCH FUNKTIONELL STIL17 / 32

CLOSURES


Varje anrop får ett eget scope

createCounter()har kört klart, men scopet lever kvarcount0increase, valueminns countreturnconst a = createCounter()count3egen countconst b = createCounter()count1egen counta.count är undefined: count går inte att nå utifrån
MODERN JAVASCRIPT OCH FUNKTIONELL STIL18 / 32

CLOSURES


createCounter

Fabriken

const createCounter = () => {
  let count = 0;
  return {
    increase: () => { count++; },
    value: () => count,
  };
};

Två räknare

const a = createCounter();
const b = createCounter();
a.increase();
a.increase();
b.increase();

a.value();  // 2
b.value();  // 1
a.count;    // undefined
MODERN JAVASCRIPT OCH FUNKTIONELL STIL19 / 32

CLOSURES


Samma TodoList, två sätt

Tisdagens klass, och samma API med en closure.

Med klass

class TodoList {
  #todos = [];
  add(text) {
    this.#todos.push(text);
  }
  get all() {
    return [...this.#todos];
  }
}
const list = new TodoList();

Med closure

const createTodoList = () => {
  let todos = [];
  return {
    add: (text) => {
      todos = [...todos, text];
    },
    all: () => [...todos],
  };
};
const list = createTodoList();
MODERN JAVASCRIPT OCH FUNKTIONELL STIL20 / 32

CLOSURES


Klass eller closure?

Privat data

Klassen: #todos. Closuren: en vanlig variabel som bara funktionerna ser.

this

Klassens metoder tappar this om du lyfter ut dem. Closurens funktioner använder inget this, så const { add } = list fungerar.

new och instanceof

Bara klassen. Behöver du instanceof eller arv är klassen naturligare.

Smaksak, mest

För den som använder objektet är skillnaden liten. Välj det teamet läser lättast, och var konsekvent.

MODERN JAVASCRIPT OCH FUNKTIONELL STIL21 / 32

CLOSURES


Closures ni redan har skrivit

Koden

for (const song of songs) {
  const button =
    document.createElement('button');
  button.textContent = song;
  button.addEventListener('click',
    () => console.log(song));
  main.append(button);
}

Varför fungerar det?

Loopen har kört klart långt innan någon klickar. Varje varv har ett eget song, och varje callback minns sitt. Det är en closure.

MODERN JAVASCRIPT OCH FUNKTIONELL STIL22 / 32
04

Kassan

Gör en imperativ kassa ren.

KASSAN


En kassa som fungerar en gång

Kör checkout('STUDENT') två gånger med samma varor. Gissa först.

kassa-imperativ.js (utdrag)

let total = 0;

export function checkout(code) {
  for (...) {
    if (discountCodes[code]) {
      product.price = product.price
        * (1 - discountCodes[code]);
    }
    line.sum = product.price * line.quantity;
    total = total + line.sum;
  }
  console.log(receiptText);
}

Vad är orent?

Hitta minst fyra saker innan du läser vidare i noterna.

MODERN JAVASCRIPT OCH FUNKTIONELL STIL24 / 32

Övning

Del A: gör kassan ren

Skriv rena funktioner i js/receipt.js i repot js--fp-kassan: findProduct, lineTotal, subtotal, applyDiscount, vatOf och formatReceipt. Ingen av dem får ändra products eller lines, läsa globala variabler eller logga. Använd dem i main.js, som är det enda stället med sidoeffekter.

Tid

15 min

Mål

Samma köp ger samma kvitto, hur många gånger du än kör.

MODERN JAVASCRIPT OCH FUNKTIONELL STIL25 / 32

KASSAN


Ett förslag

receipt.js

export const lineTotal = (line, products) =>
  findProduct(products, line.productId)
    .price * line.quantity;

export const subtotal = (lines, products) =>
  lines.reduce(
    (sum, line) => sum + lineTotal(line, products),
    0,
  );

export const applyDiscount = (amount, code, codes) =>
  amount * (1 - (codes[code] || 0));

main.js

console.log(
  formatReceipt(lines, products, 'STUDENT',
    discountCodes, VAT_RATE),
);
MODERN JAVASCRIPT OCH FUNKTIONELL STIL26 / 32
05

När passar
vad?

KURSMÅL 3


OOP eller funktionell stil?

OOP passar

Saker med eget tillstånd som lever en stund och ändras: en spelare, en kortlek, en anslutning. När du vill ha instanceof, arv eller ett tydligt API runt datan.

Funktionell stil passar

Data som omvandlas: listor som filtreras, räknas om och formateras. Logik som ska testas. Det mesta i en frontend som visar data.

Oftast båda

Rena funktioner för beräkningarna, och ett objekt eller en closure för det tillstånd som måste finnas. Kassan är ett exempel.

MODERN JAVASCRIPT OCH FUNKTIONELL STIL28 / 32
”

OOP gömmer mutationen bakom metoder. Funktionell stil undviker den, och samlar det som ändå måste ändras på ett ställe.

06

Efter passet

EFTER PASSET


Till torsdagens workshop

Ta med två egna lösningar. På torsdag granskar ni varandras kod i par.

  • Kassan, del B (js--fp-kassan): createCart(products) i js/cart.js, med add, remove, lines() och total(). Raderna bor i en closure. Inga push, inga splice.
  • Kassan, del C: visa kvittot på sidan i stället för i konsolen. Bara main.js får röra DOM:en.
  • Pokern (js--oop-poker): minst del 1–4, från tisdagen.
  • Lägg båda på GitHub, så att en kamrat kan granska dem i en pull request.
MODERN JAVASCRIPT OCH FUNKTIONELL STIL31 / 32

EFTER PASSET


Mer att läsa

  • Video: Learning Functional Programming with JavaScript, Anjana Vakil (JSUnconf), om du inte såg den före passet.
  • Closures (MDN): developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures
  • Fördjupning: JavaScript: The Best of Both Worlds, OOP and Functional Programming (Medium), samma text som i tisdags.
MODERN JAVASCRIPT OCH FUNKTIONELL STIL32 / 32

Modern JavaScript och funktionell stil

By sandra-larsson

Modern JavaScript och funktionell stil

  • 1