Översikt
Kursvecka fem och nu är du verkligen igång! Nu gäller det att verkligen borra ner huvudet och jobba på. Du går in i en lite tyngre period av kursen nu med ständigt nya koncept som bygger på tidigare veckor. Denna vecka introduceras objekt. Information om veckans upplägg annonseras löpande i kursens Zulip-kanal.
Veckostart med objekt
Section titled “Veckostart med objekt”Tisdagen i kursvecka 5 inleddes med frågor om A2, bland annat om det sorterade typvärdet, validering
och reflektionsdokumentet, och om hur du sparar, committar och pushar med Git. Därefter livekodade
Mikael grunderna i objektlitteralen, från egenskaper och for...in till en fabriksfunktion med en
metod, som leder rakt in i veckans övningsuppgifter med klockor.
Om passet
Section titled “Om passet”Tisdagens pass i kursvecka 5 hölls av Mats och Mikael tillsammans och bestod av två delar. Först besvarades inskickade frågor, framför allt om examinationsuppgift A2 och om hur man arbetar med Git. Därefter introducerade Mikael objektlitteralen genom att livekoda i sitt playground-projekt. Passet avslutades med en genomgång av veckans två första övningsuppgifter, som bygger direkt vidare på livekodningen.
Veckans material och omexamination av A1
Section titled “Veckans material och omexamination av A1”Veckans tema är objekt, och en del av A2 kräver att du kan skapa och använda objekt. Objekt, klasser och det som följer av dem återkommer under flera veckor framöver, så det här är en början. Den stödjande inspelningen om objekt kan behöva ses mer än en gång, och det finns en uppdaterad presentation att följa med i. Övningsuppgifterna visar hur objekt är tänkta att användas.
Missade du testet A1 för två veckor sedan, eller blev du inte godkänd, får du en ny chans på torsdag. Är du redan godkänd behöver du inte göra något.
A2: typvärdet ska vara sorterat
Section titled “A2: typvärdet ska vara sorterat”En fråga gällde varför testerna för mode (typvärde) kräver att en array med flera typvärden är
sorterad, när det inte står i uppgiftsbeskrivningen. Svaret är att det är testerna som gäller: de
måste passera, och där kravtexten är ofullständig är det testerna som definierar vad som förväntas.
Mats bekräftar att kravet saknas i beskrivningen, att det är ett misstag från hans sida och att det
är åtgärdat till nästa kursomgång.
Validering i varje funktion — och DRY
Section titled “Validering i varje funktion — och DRY”Ska varje funktion undersöka att indata är giltigt och kasta ett undantag annars? Ja. Frågeställaren
insåg själv att det då blir samma if-satser på sex–sju ställen, och undrade om det är ett exempel
på principen DRY (don’t repeat yourself). Det är det definitivt, och det kan vara läge att bryta
ut valideringen i en egen funktion. Det är ingen underkänningsgrund att upprepa if-satserna, men
du kan få en kommentar om det. Resonemanget är detsamma som i förra veckans torsdagspass: lös
uppgiften först, luta dig sedan tillbaka och se om koden kan skrivas snyggare.
Behöver valideringsfunktionen exporteras? Nej, den är en intern detalj i modulen. En funktion som inte exporteras är osynlig utanför modulen och kan ses som privat. Det gör inget om den ändå exporteras, men det finns ingen anledning till det.
Var skriver jag vad?
Section titled “Var skriver jag vad?”All kod skrivs i statistics.js. Det är den filen som bedöms. README-filen ska inte redigeras. Utöver
koden finns reflektionsdokumentet REFLECTION.md i repots rot, där du reflekterar över uppgiften och
särskilt över hur du eventuellt arbetat med AI.
En fråga gällde att bara vissa frågor i dokumentet följs av raden Svar:. Svaret är att du ska
besvara samtliga, även där det inte står Svar:. Under Använda verktyg ersätter du exempelraden
med en punkt (* följt av namnet på AI-assistenten), eller skriver att du inte använt någon. Mats
tar med sig frågan och ser över mallen, eftersom fler än frågeställaren troligen tyckt att den var
otydlig.
Dokumentet är skrivet i Markdown, för de flesta är det första gången i kursen. Markdown är i grunden vanlig text som på GitLab visas som HTML. I VS Code kan du förhandsgranska filen (Open Preview, t.ex. via högerklick på filen eller Ctrl+Shift+V) för att se om texten behöver fler stycken. Formatet är mycket vanligt, från dokumentation på GitHub och GitLab till instruktioner till AI-assistenter, och hela kursens webbplats bygger på varianter av Markdown. Ingen annan editor behövs för att skriva det.
Spara, committa, pusha
Section titled “Spara, committa, pusha”En längre fråga handlade om hur ofta man ska committa och vad skillnaden är mellan att spara, committa
och pusha. Mats svar i en kurs är: committa så ofta det går. Så fort du gjort en ändring och börjar
fundera på nästa steg är det dags. Ju mindre varje commit är, desto lättare är det att skriva ett
vettigt meddelande. Mikael ser en commit som ett sätt att släppa tankarna på den bit han just gjort
klar. För A2, med sina sju funktioner som ska skapas (plus summary som ska färdigställas), blir det
minst en commit per funktion, och gärna fler när testerna avslöjar fel som rättas.
Med bilden från Git-introduktionen i kursvecka 2 som stöd:
- Spara i VS Code skriver bara filen till arbetskatalogen (working directory). Git är ännu inte inblandat.
git addtalar om för Git vilka ändrade filer som ska med (staging area).git add .tar med alla ändrade filer.git commit -m "..."lägger till ändringarna i historiken i det lokala repot, fortfarande bara på din dator.git pushskickar commits till fjärrrepot (remote) på GitLab.
Mikael kör git status innan han committar, för att se vad som behöver läggas till. Han pushar
direkt efter varje commit, delvis av backupskäl. Push har dessutom två andra effekter. Den startar
pipelinen, så testerna körs även på servern. Och den ger en tidsstämpel på servern som, till skillnad
från datumen i själva commits, är mycket svår att manipulera. Därför säger avsnittet om akademisk
integritet att du ska pusha ofta och regelbundet till ett repo kursledningen har tillgång till.
Har du väl klonat ditt repo behöver du aldrig klona det igen. Du sparar, committar och pushar, och fortsätter sedan arbeta i samma katalog. Det är just det som gör att versionshistoriken visar hur arbetet fortskridit.
Commit-meddelanden
Section titled “Commit-meddelanden”Guiden Commit-meddelanden från kursvecka 2
beskriver hur de skrivs. Mikael skriver sina på engelska och i imperativ form, som en order: Add,
Remove, Delete. Meddelandet beskriver vad commiten gör med den befintliga koden.
Ingen har blivit underkänd för dåliga commit-meddelanden, men de påverkar helhetsintrycket, åt båda hållen. I ett längre perspektiv är tydliga meddelanden en del av mjukvarans kvalitet och dokumentation. Det har blivit än viktigare nu när AI-assistenter läser igenom både kod och commit-historik för att bilda sig en uppfattning om ett projekt.
Övriga frågor
Section titled “Övriga frågor”- Måste jag använda VS Code? Nej. Kursen använder VS Code för att det är enkelt att komma igång med och fungerar på alla plattformar, och det används i utbildningens övriga kurser oavsett språk. Vill du prova en annan editor står det dig fritt.
- Kan jag börja om med A2? Den lokala kopian kan du radera och klona igen. Vill du ha ett helt nytt repo på GitLab måste kursledningen radera projektet. Skriv till Mats på Zulip, så kan du därefter skapa det på nytt via ActionHub. Då försvinner allt som pushats.
Livekodning: varför objekt?
Section titled “Livekodning: varför objekt?”Mikael öppnar en ny fil i sitt playground-projekt och talar om objektlitteral, eftersom “objekt” kan
betyda väldigt mycket i olika språk. En variabel lagrar ett värde. En array lagrar många värden av
samma slag, t.ex. två, tre eller 50 000 namn. Vill du i stället klumpa ihop värden av olika typ som
hör ihop, t.ex. ett namn och en ålder, är objektet rätt verktyg. Det går att lägga strängen 'Mats'
och talet 42 i en array i JavaScript, men så ska man inte göra.
En array skapas med hakparenteser, ett objekt med klammerparenteser (måsvingar, curly braces):
const mats = { name: 'Mats', age: 42 }const mikael = { name: 'Mikael', age: 42 }
console.log(mats) // { name: 'Mats', age: 42 }console.log(mats.name) // Matsconsole.log(mikael.age) // 42Innehållet består av egenskaper (properties): par av en nyckel och ett värde (key-value pairs,
ibland namn-värde-par). En array består av värde, värde, värde, ett objekt av nyckel, värde,
nyckel, värde. Med punktnotation (mats.name) pekar du ut en enskild egenskap.
Ett sidospår: console.log({ mikael }) skriver ut objektet tillsammans med variabelns namn,
{ mikael: { name: 'Mikael', age: 42 } }, vilket är praktiskt vid felsökning. Mats mindes först att
det fungerar även för { mikael.age }, men det är ett syntaxfel.
Stavfel, undefined och NaN
Section titled “Stavfel, undefined och NaN”Vad händer om man stavar fel på en egenskap?
console.log(mikael.Age) // undefined
mikael.Age += 1console.log(mikael.Age) // NaNJavaScript skiljer på stora och små bokstäver, så Age och age är olika egenskaper. En egenskap
som inte finns ger undefined, och undefined + 1 är ingen giltig numerisk beräkning, så resultatet
blir NaN (Not a Number). Tilldelningen skapar dessutom egenskapen Age med värdet NaN, i
stället för att ge ett fel. Kuriosa: typeof NaN är 'number'.
Det här är en vanlig felkälla i början, och NaN kan dyka upp i A2 också, när en lång beräkning
plötsligt resulterar i NaN. Mats konstaterar att JavaScript nog inte hade betett sig så om det
skapats i dag. Språket togs fram på tio dagar 1995, och det får man leva med 30 år senare.
Objekt är föränderliga
Section titled “Objekt är föränderliga”Objekt kan ändras efter att de skapats, de är mutable (föränderliga). Mikael ger sig själv en moped och tar bort den igen:
mikael.moped = trueconsole.table(mikael)
delete mikael.mopedconsole.table() skriver ut objektet som en tabell. Som jämförelse är strängar immutable: en
sträng kan inte ändras, i stället skapas en ny.
Objekt som argument och loopar med for...in
Section titled “Objekt som argument och loopar med for...in”Ett objekt kan skickas som argument till en funktion, som sedan använder dess egenskaper:
function describe(person) { return `${person.name} is ${person.age} years old.`}
const result = describe(mats)console.log(result)För arrayer används for...of. För att loopa igenom ett objekts egenskaper används for...in, som
ger egenskapernas namn. Det är användbart när man inte vet exakt vilka egenskaper ett objekt har,
t.ex. för att det ändrats under körningen. Mikael skriver först mats.prop i loopen och får
undefined. Det letar efter en egenskap som faktiskt heter prop. Eftersom namnet ligger i en
variabel krävs hakparentesnotation:
for (const prop in mats) { console.log(`Property ${prop} has the value ${mats[prop]}`)}// Property name has the value Mats// Property age has the value 42Det är just det fall hakparentesnotationen är till för: när egenskapens namn är dynamiskt. I andra fall gäller punktnotation.
En fabriksfunktion med en metod
Section titled “En fabriksfunktion med en metod”Vad gör man om man behöver många personer med samma struktur? Mikael skriver en funktion som skapar och returnerar ett nytt objekt. Ett egenskapsvärde kan vara vilken datatyp som helst, även en funktion. En funktion som ligger i ett objekt kallas metod:
function createPerson(name, age) { return { name, age, greet() { return `Hello, I am ${this.name} of ${this.age} years.` } }}
const my = createPerson('My', 42)console.log(my.greet()) // Hello, I am My of 42 years.name och age är en kortform för name: name och age: age, när variabeln och egenskapen har
samma namn. Resultatet är fortfarande en objektlitteral. Objektet samlar data om personen
(egenskaperna) och det personen kan göra (metoderna). Det är en försmak av nästa veckas tema,
klasser.
Mikael och Mats kallar konstruktionen för factory. Det är namnet på ett designmönster, en återkommande, namngiven lösning på ett vanligt problem. Designmönster återkommer senare i utbildningen och behöver inte pluggas nu. Mikael kopplar också ihop det med inkapsling: data och metoder som hör ihop paketeras tillsammans. Mats fyller i att objekt (liksom moduler) inte bör exponera mer än det som behövs, något som blir enklare att hantera när klass-syntaxen introduceras. Tanken är densamma som i frågan om valideringsfunktionen i A2 behöver exporteras.
Veckans övningsuppgifter
Section titled “Veckans övningsuppgifter”- Literal klocka bygger direkt på livekodningen: en objektlitteral
literalWatchmed egenskapernahourochminuteoch metodernaaddMinutesochtoString. Uppgiften har inga tester, så du kör programmet mednpm startoch jämför utskriften med den förväntade. Räkna gärna ut i förväg vad klockan borde visa, t.ex.17:04plus 59 minuter. - Fabricerad klocka går vidare till en fabriksfunktion,
createWatch, på samma sätt somcreatePersonovan. Observera att uppgiften går ett steg längre än livekodningen: metoderna ska inte skapas på nytt i varje objekt, utan delas via ett gemensamt prototypobjekt (Object.create()), och egenskaperna skyddas med getters och setters. - Reducerad array med objekt kombinerar arrayer, objekt och validering av indata med undantag, alltså precis det som frågorna om A2 handlade om.
Nytt för i år är att uppgifterna har sekvensdiagram. Diagrammet läses uppifrån och ned, och pilarna
visar anropen fram och tillbaka mellan programmet och objektet, t.ex. att toString() ska returnera
'17:04'. Både Mats och Mikael känner ett motstånd första gången de ser ett stort sekvensdiagram,
men det lönar sig att ta sig över tröskeln. Diagrammet beskriver hela flödet, och har du förstått det
har du i stort sett lösningen framför dig.
Torsdag med prototyper och reduce
Section titled “Torsdag med prototyper och reduce”Torsdagen i kursvecka 5 började med utmaning 05-03 och en förklaring av JavaScripts prototypkedja,
följd av frågor om hur du kommer igång med A2, vad som händer om du missar deadline och om
AI-kodkomplettering. Därefter löste Mikael övningsuppgifterna Reducerad array och Reducerad array med
objekt live, först med en loop och sedan med reduce, och diskuterade när den kortare lösningen är
din egen.
Om passet
Section titled “Om passet”Torsdagens pass i kursvecka 5 hölls av Mats och Mikael tillsammans och bestod av två delar. Först
besvarades inskickade frågor: om utmaning 05-03 och JavaScripts prototypkedja, om hur du kommer igång
med A2 och vad som händer om du missar deadline, om AI-kodkomplettering och om hur mycket som måste
fastna från kurslitteraturen. Därefter löste Mikael övningsuppgifterna Reducerad array och Reducerad
array med objekt live, först med en for...of-loop och sedan med reduce.
Utmaning 05-03: vad skrivs ut?
Section titled “Utmaning 05-03: vad skrivs ut?”Passet började med en fråga om den tredje av veckans utmaningar, där
Object.create() dyker upp:
const objPrototype = { prop: 10, toString() { return `I have ${this.prop} somethings!` },}
const createObject = function (quantity = 0) { const obj = Object.create(objPrototype) obj.prop = quantity return obj}
const obj = createObject(12)
console.log(obj.toString())Mats påminner först om syftet med utmaningarna. De är konstruerade för peer instruction, alltså för att väcka diskussion, och därför är de gärna lite luriga. Det är inte den typen av frågor som ställs vid de muntliga examinationerna.
Mikael läser koden uppifrån och ned och känner igen det mesta från tisdagens livekodning:
objPrototype är en objektlitteral med en egenskap och en metod, och createObject är en
fabriksfunktion (factory) med ett standardvärde på parametern. Det nya är Object.create(). Han
följer sedan anropet: obj.prop sätts till 12, och toString() returnerar I have 12 somethings!, vilket är rätt svar.
Svårigheten, säger Mikael, är att han står med tre ben samtidigt: ett i tisdagens enkla objektlitteraler, ett i nästa veckas klasser och ett tredje, som utmaningen tvingar fram, i hur JavaScripts grundläggande objektmodell fungerar.
Prototypkedjan
Section titled “Prototypkedjan”Mats visar en bild över vad som händer. Koden skapar två objekt: prototypobjektet som objPrototype
refererar till, och det nya objektet som obj refererar till. Object.create(objPrototype) skapar ett
nytt, tomt objekt vars prototyp är objPrototype. Ovanför dem båda finns dessutom ett tredje
objekt, rotobjektet, som varje vanlig objektlitteral har som prototyp, även tisdagens objekt, fast det
aldrig syntes.
När obj.toString() anropas letar JavaScript först efter toString i obj självt. Där finns den
inte, så sökningen fortsätter i obj:s prototyp, objPrototype, där metoden hittas och körs. Inuti
metoden står this.prop, och då börjar sökningen om från obj. Där finns en egen egenskap prop
med värdet 12, så den används, trots att prototypen har en prop med värdet 10. Den egna
egenskapen skuggar prototypens (property shadowing).
Mats tumregel, som han själv säger inte är tekniskt sann men fungerar i huvudet: det är objektet som kör koden. Utgå från det objekt du anropar metoden på. Har det egenskapen är det dess värde som gäller.
Varför prototyper?
Section titled “Varför prototyper?”Tänk dig tusen objekt av samma slag. Utan en gemensam prototyp skulle varje objekt bära på sin egen
kopia av toString(). Med en prototyp finns metoden på ett enda ställe och delas av alla objekt som
skapats utifrån den. Prototypen fungerar som en mall med standardvärden för egenskaper och metoder,
som det enskilda objektet kan ersätta med egna (override):
const a = createObject(12)const b = Object.create(objPrototype)
console.log(a.toString()) // I have 12 somethings!console.log(b.toString()) // I have 10 somethings!b har ingen egen prop, så värdet hämtas från prototypen.
Det här är JavaScripts prototypbaserade objektmodell, och den fungerar på ett helt annat sätt än i till exempel C++, C# och Java. Klass-syntaxen, som introduceras nästa vecka, kom först med ES2015 och kallades av belackare för syntaktiskt socker, eftersom allt under ytan fortfarande fungerar precis så här. Prototyperna lånades från språket Self, en dialekt av Smalltalk, där i princip allt är objekt. Är det här snårigt behöver du inte oroa dig: det kommer att falla på plats under kursens gång. Det är också precis det som övningsuppgiften Fabricerad klocka tränar på.
Kom igång med A2
Section titled “Kom igång med A2”En fråga gällde hur man kommer igång med A2 över huvud taget. Svaret är att det inte skiljer sig så mycket från övningsuppgifterna, förutom att du inte forkar repot utan skapar det via ActionHub enligt anvisningarna. Därefter klonar du det och arbetar som vanligt.
- Steg-för-steg-instruktionerna finns under examinationsuppgiften i kursvecka 3, och guiderna för VS Code finns i kursvecka 2.
- All kod skrivs i
src/statistics.js, och reflektionerna iREFLECTION.md. - Du ska göra minst 15 commits, och gärna pusha efter varje.
- Allt står inte i README-filen. Uppgiften har 17 issues som beskriver kraven mer i detalj. Sedan en uppdatering av GitLab kallas de i gränssnittet för work items.
- Läs igenom hela README-filen och alla issues först, även om du inte förstår allt. Djupläs sedan när du behöver.
- Sju funktioner ska implementeras, i valfri ordning. README-filen länkar till förklaringar av begrepp som median, typvärde (mode) och standardavvikelse (standard deviation).
- Kör testerna, alla eller ett urval, och prova din kod i
app.jsmednpm start. - När du är klar lämnar du in via en merge request, enligt anvisningarna.
Mikaels råd är att göra en självkoll innan du börjar: hur många övningsuppgifter har du gjort på egen hand? Kan du räkna upp ett par är du troligen tillräckligt förberedd. Övningsuppgifterna är starkt kopplade till examinationsuppgiften. Hoppar du direkt på A2 utan att ha arbetat med kursens material kommer du att lägga mycket tid på sådant som tas upp i guiderna och övningarna.
Vad händer om jag missar deadline?
Section titled “Vad händer om jag missar deadline?”Ingenting, egentligen. Det finns alltid en omexamination, och den som lämnar in till den bedöms precis som den som lämnar in till ordinarie deadline. Märker du att du är på väg att ta enorma genvägar för att hinna, kan det vara bättre att sikta på nästa deadline.
Mikael lägger till ett perspektiv: missar du den första deadlinen kan det vara en signal till dig själv om hur du förhåller dig till kursen och planeringen. Det kan finnas många skäl, men det kan vara värt att fundera över. Och klarar du en deadline ska du vara nöjd och stolt.
AI-kodkomplettering, igen
Section titled “AI-kodkomplettering, igen”En student som inte varit med på tidigare pass berättade att VS Code ger färdiga lösningsförslag som blir hela koden med ett tryck på Tab, och undrade om det ska vara så. Frågan togs även upp förra torsdagen. Det är inte förbjudet, och det är troligen en standardinställning, inte något som kom med kursens instruktioner. Mikaels korta svar är ändå: stäng av det. Förslagen är för snälla, och då stöter du aldrig på problemen själv.
Mats har allt aktiverat, men han är senior programmerare och sitter med fingret på Esc för att avfärda förslagen. Han tror att man inledningsvis lär sig mer av att skriva och fundera själv, men att det är bättre att använda hjälpmedlen än att sitta fast utan att komma vidare. Övningarna är så pass enkla, och kommentarerna i koden så tydliga, att en AI-assistent lätt knäcker dem. Den vet dock inte vilken lösning som är bäst för dig, och den bästa lösningen är den du förstår.
Med A2:s sju funktioner kan hela uppgiften i princip lösas med sju tryck på Tab. Kursledningen kan inte göra något åt det, så ansvaret ligger hos dig: välj en väg som är bra för ditt lärande. Mikael berättade om en vän, inte programmerare, som byggt avancerade program med AI men nått en nivå där även små ändringar tog lång tid. Dålig arkitektur gör koden svår att underhålla och vidareutveckla, och där behövs en kunnig programmerare även när AI blir bättre.
Får man då använda AI i A2, där man ska agera Tech Lead över sina AI-verktyg? Ja, utan begränsningar. Det som alltid gällt är att du ska äga det du lämnar in: kunna stå för det och förstå allt till punkt och pricka.
Måste allt i boken fastna?
Section titled “Måste allt i boken fastna?”En student har svårt att lära sig programmering genom att läsa och undrade om det gör något att inte allt fastnar, så länge hen hänger med i övrigt och gör övningsuppgifterna. Både Mats och Mikael känner igen sig: de måste göra, och ibland misslyckas några gånger, för att lära sig. Hänger du med och gör övningsuppgifterna är det bara att gratulera. Meningen är inte att du ska kunna återge boken, utan att du ska kunna tillämpa det.
Livekodning: Reducerad array
Section titled “Livekodning: Reducerad array”Mikael klonar övningsuppgiften Reducerad array, kör npm i och tittar i app.js. Uppgiften är att
komplettera funktionen getSum i src/array-sums.js, som ska summera talen i en array, och han
noterar direkt att den har en tydlig koppling till A2. Han arbetar på sitt vanliga sätt, med
console.log() i stället för debuggern, och skriver först ut det som kommer in. Sedan summerar han
med en loop:
export function getSum(data) { let sum = 0 for (const element of data) { sum += element } return sum}Summan måste ha ett startvärde, därav let sum = 0. Med npm start ger anropen 6, 20, 20 och
0, vilket stämmer med indata.
Testerna i tre grupper
Section titled “Testerna i tre grupper”Testerna är indelade i tre describe-grupper: return value, side effects och exceptions. Med
test:match (se guiden) kör Mikael en grupp i taget:
npm run test:match -- "return value"Då hoppas de sju andra testerna över. Ett stavfel i mönstret ger däremot elva överhoppade tester och
inga som körs. return value och side effects går igenom direkt, men exceptions blir rött.
README-filen kräver att ett TypeError med meddelandet The passed argument is not an array. kastas
om argumentet inte är en array. Mikael kopierar strängen exakt från README-filen, eftersom testerna är
kinkiga: en glömd punkt räcker för att det ska bli fel. Första försöket går ändå inte igenom. Villkoret
saknade !, så undantaget kastades när argumentet var en array. Rättat ser det ut så här:
if (!Array.isArray(data)) throw new TypeError('The passed argument is not an array.')Formatering och klammerparenteser
Section titled “Formatering och klammerparenteser”Tekniskt sett är uppgiften nu klar, men Mats påpekar att koden innehåller bortkommenterad kod och är
inkonsekvent: for-loopen har klammerparenteser men if-satsen inte, fast båda bara innehåller en
sats. npm run format (Prettier) lät if-satsen stå utan klammerparenteser och lade den dessutom på en
enda rad, eftersom den ryms inom radlängden på 120 tecken.
För ett år sedan hade Mikael aldrig skrivit så, och han hade påpekat det för studenter. Efter att ha
läst mycket AI-skriven kod det senaste halvåret har han ändrat sig och har inga problem med det
längre. Mats skriver däremot alltid block med klammerparenteser, en defensiv stil han lade sig till
med för 30 år sedan, när ett glömt end i Pascal kostade honom tre dagars felsökning.
Vad som gäller varierar mellan organisationer. Det viktiga är att du förhåller dig till de regler som gäller i sammanhanget, och i kursen är det lintern och formateraren: säger de att koden är okej, så är den okej.
Samma sak med reduce
Section titled “Samma sak med reduce”Uppgiften heter Reducerad array av en anledning. Mikael skriver om summeringen med
Array.reduce:
export function getSum(data) { if (!Array.isArray(data)) throw new TypeError('The passed argument is not an array.')
return data.reduce((sum, element) => sum + element, 0)}reduce går igenom arrayen och reducerar den till ett enda värde. Callback-funktionen, här en
pilfunktion, anropas en gång per element med det ackumulerade värdet och det aktuella elementet.
Dokumentationen kallar parametrarna accumulator och currentValue, men Mats föreslår namn som
beskriver vad de faktiskt är i just det här fallet: sum och element. Det andra argumentet, 0, är
startvärdet.
Mats poängterar att for-loopen fungerar på samma sätt i nästan alla språk, medan reduce är mer
specifik för JavaScript, även om andra språk har motsvarigheter under andra namn. Konstruktionen är
mycket vanlig, men den är svår att förstå om man inte först förstått vad loopen gör.
En följdfråga gällde om den exporterade funktionen också kan skrivas som en pilfunktion. Det kan den:
export const getSum = (data) => { // ...}I det här fallet är det samma sak, och det är en smakfråga vilken form du väljer. Det finns
skillnader, till exempel kan en funktionsdeklaration anropas innan den definierats i koden (den
hoistas) och pilfunktioner har inget eget this, men de spelar ingen roll här.
Reducerad array med objekt
Section titled “Reducerad array med objekt”Nästa övningsuppgift är likadan, med en skillnad: arrayen innehåller objekt. Mikael kopierar sin
felhantering från förra uppgiften. Det leder till en kort diskussion om att kopiera egen kod. Fördelen
är att du bygger upp en bank av kodkonstruktioner du vet fungerar. Nackdelen är att du, om du bara
kopierar, har svårt att skriva till exempel Array.isArray() själv den hundraförsta gången. Det finns
ett värde i att mekaniskt skriva koden några gånger.
En utskrift med console.log() visar att varje element är ett objekt, det syns på klammerparenteserna,
med egenskapen nr. Då är det bara att summera egenskapen:
let sum = 0for (const element of data) { sum += element.nr}return sumÄven den här skriver Mikael sedan om med reduce, och glömmer först .nr, så testerna slår fel tills
han rättar callbacken till (sum, element) => sum + element.nr.
Får jag använda reduce i A2?
Section titled “Får jag använda reduce i A2?”Ja, du får använda vilka konstruktioner du vill, så länge du förstår och kan förklara dem. Skulle Mats få in båda lösningarna av olika studenter vore båda lika rätt. Mikaels rekommendation för en skoluppgift är ändå loopen, eftersom den ligger närmast till hands.
Mats har dock sett att många A2-inlämningar har mycket korta lösningar med reduce, ibland försedda
med förklarande kommentarer ovanför varje rad. Få studenter skriver den koden på egen hand, medan det
är ett mycket vanligt sätt för en AI att lösa uppgiften. Han berättar om en inlämnad A2 som var en
mycket “senior” lösning, men där studenten vid den muntliga examinationen av en senare uppgift inte
kunde svara på frågor om koden. A2 är enkel jämfört med A3 och senare uppgifter, där du måste kunna
hela kodbasen och hitta i den. Det är där det kör ihop sig om du inte har koll, så träna på varje liten
byggsten nu.
Mikael avslutar: han blir glad av slarvig kod i A2, för då finns det något att prata om, och likaså av reflektionstexter med stavfel och syftningsfel. Mats håller med. Och nej, det är inte fel att som nybörjare skriva många kommentarer i koden. Mats kallar dem pedagogiska kommentarer. Allt som främjar lärandet är bra, och behovet av dem minskar med tiden.
Stödjande inspelningar
Section titled “Stödjande inspelningar”Objekt
Section titled “Objekt”Objekt är något oerhört centralt i JavaScript och i all objektbaserad programmering. Denna inspelning introducerar objekt ur dess allra renaste form.
PresentationSkapa ett objekt
Section titled “Skapa ett objekt”Ett objekt skapas med två klammerparenteser, precis som en array skapas med två hakparenteser:
const lovelace = {}Även ett “tomt” objekt är i praktiken inte helt tomt. I bakgrunden finns alltid ett grundobjekt, Object, som varje objekt i JavaScript i grunden bygger vidare på – ungefär som en tom array redan har egenskaper som length och metoder som push. Det går att skapa ett objekt med new Object() också, men {} – en objektlitteral – är det moderna och rekommenderade sättet.
Ett objekt är ett sätt att paketera data. Till skillnad från en array – som ska hålla samma datatyp i varje element – kan ett objekt fritt blanda tal, strängar, booleaner och referenser till andra objekt.
Egenskaper och prototypkedjan
Section titled “Egenskaper och prototypkedjan”Det som finns i objektet kallas egenskaper (properties), och varje egenskap är i grunden ett nyckel-värde-par: en nyckel (namnet på egenskapen) kopplad till ett värde. Utöver de egenskaper man själv lägger till har varje objekt en intern egenskap (skriven __proto__) som pekar mot det bakomliggande grundobjektet – prototypen. Interna egenskaper av det slaget, inramade med dubbla understreck, ska man varken läsa eller ändra direkt; JavaScript sköter dem själv.
Anropas en metod som inte finns direkt på objektet letar JavaScript vidare uppåt i prototypkedjan. Finns metoden inte där heller blir det ett fel. Det här förklarar varför lovelace.toString() fungerar på ett objekt som aldrig själv fått en toString-egenskap – den hittas i stället på prototypen.
Sätta och hämta en egenskap
Section titled “Sätta och hämta en egenskap”Egenskaper sätts och hämtas med punktnotation:
lovelace.firstName = 'Ada'lovelace.lastName = 'Lovelace'
console.log(lovelace.firstName) // OUTPUT: AdaFinns inte egenskapen redan skapas den; finns den redan skrivs värdet över. JavaScript är här mycket tillåtande – stavar man fel skapas helt sonika en ny egenskap istället för att ett fel uppstår, vilket kan vara nog så lurigt att felsöka.
Det går även att komma åt egenskaper med hakparentesnotation (lovelace['firstName']), men kursens kodstandard kräver punktnotation eftersom det är tydligare – hakparenteser är egentligen till för fall där namnet på egenskapen i sig är dynamiskt (lagrat i en variabel), inte hårdkodat.
Egenskaper kan också sättas direkt när objektet skapas, med kolon istället för likhetstecken och kommatecken mellan varje par:
const lovelace = { firstName: 'Ada', lastName: 'Lovelace'}Ta bort en egenskap
Section titled “Ta bort en egenskap”Nyckelordet delete tar bort en egenskap helt:
delete lovelace.birthYearAtt istället sätta värdet till undefined är inte samma sak – då finns egenskapen kvar, bara med ett tomt värde.
Metoder – en egenskap vars värde är en funktion
Section titled “Metoder – en egenskap vars värde är en funktion”En egenskap vars värde är en funktion kallas en metod. Det finns flera sätt att skriva en, men det kortare, nyare sättet (sedan ES6/2015) är att utelämna både kolon och function:
const lovelace = { firstName: 'Ada', lastName: 'Lovelace', says () { return `Hi, I'm ${this.firstName}` }}
console.log(lovelace.says()) // OUTPUT: Hi, I'm AdaNotera return – låter man metoden console.log direkt istället för att returnera strängen bryter man mot separation of concerns: metoden bör lämna ifrån sig ett värde, inte själv bestämma hur det skrivs ut.
Nyckelordet this refererar till det objekt som “kör koden” – mer precist: det objekt en metod anropas för. Anropas lovelace.says() sätts this att referera till lovelace under körningen av says. Fördelen är att metoden blir generell – den bryr sig inte om objektet råkar heta lovelace eller något helt annat, och kan därmed återanvändas rakt av på flera olika objekt istället för att hårdkoda ett specifikt variabelnamn inuti sig själv.
Undvika upprepning av kod
Section titled “Undvika upprepning av kod”Skapar man flera objekt av samma “form” – till exempel lovelace, hopper och hamilton, alla med firstName, lastName och says – hamnar samma metod dubbeldeklarerad i varje objekt. Det är upprepning av kod, precis det man vill undvika. En tanke kan vara att lyfta upp en delad metod till det gemensamma grundobjektet (Object.prototype) istället, men det är i praktiken en dålig idé – det objektet delas av alla objekt i hela programmet (och i en webbläsarmiljö av alla komponenter på sidan, oavsett vem som skapat dem), så att bygga på det riskerar att krocka med annan kod. Ett bättre svar på problemet – klasser – kommer i nästa vecka.
Läsanvisningar
Section titled “Läsanvisningar”Under läsanvisningar hittar du veckans kapitel som ska läsas i kurslitteraturen. Planera upp och dela upp läsningen under veckan.
Övningar
Section titled “Övningar”Under Övningsuppgifter hittar du övningsuppgifter som det är lämpligt att du arbetar med under veckan.
Seminarier + individuell handledning
Section titled “Seminarier + individuell handledning”Missa inte möjligheten att ställa frågor inför handledningstillfällena. Det är ett bra sätt att påverka det som tas upp i varje träff.
Examinationsuppgift A2
Section titled “Examinationsuppgift A2”Examinationsuppgift A2 finns publicerad och denna vecka är det dags att börja jobba med uppgiften. Tillsammans med veckans teorimoment har du det som krävs för att genomföra hela examinationsuppgiften. (För att komma igång se Kursvecka-03).
Omexamination av A1
Section titled “Omexamination av A1”Om du inte blev godkänd på, eller inte genomförde, examinationsuppgift A1 kursvecka 3 så bör du definitivt ta chansen denna kursvecka.
Läs mer om examinationsuppgift A1 här.
Utmaningar
Section titled “Utmaningar”Det finns en del utmaningar att titta på även denna veckan. Tänk att utmaningar kan vara bra för att komma igång med egna kodexempel kring veckans fokus.
Studiefrågor
Section titled “Studiefrågor”Här är ett antal frågor som du kan försöka besvara och diskutera tillsammans med din AI-assistent. Tveka inte att lyfta någon av frågorna till handledningen för att fortsätta diskussionen med lärare och studiekamrater.
- Förklara grunderna i konstruktionen objektliteral i JavaScript.
- Vilka är de vanligaste inbyggda metoderna som man behöver lära sig när det gäller objectliteralen?
- Kan man loopa runt properties i ett objekt?
- Vilken är den stora skillnaden mellan array och objektliteral?
- Finns det något särskilt jag bör tänka på om jag gör ett program som jobbar med objekt skapade från objektliteralen?
Här är en utskrift från hur det såg ut när jag diskuterade ovan frågor med min AI-assistent Ajj.
Här följer tips till hur du kan prioritera bland kursmaterialet för att komma igång med veckan.
- Det finns en föreläsning som ger grunden, efter den bör du kunna komma igång med både utmaningar och de blå övningsuppgifterna.
- När du kommit igång med grunden kan du se om du kan använda objekt för att lösa delar i A2, till
exempel delen med
summary(). - Försök komma en bit in på att lösa A2 under denna veckan, försök minst komma en tredjedel, men gärna halvvägs.
- Missa inte guiden om hur du bara kör enhetstesterna för en specifik funktion.