Mörkt tema
Vanliga misstag
Här kommer en lista med vanliga misstag som du kan använda som checklista.
Generellt
- Du har glömt bort "vanliga misstag" från HTML & CSS-kursen.
- Du har inte påbörjat en "checklista" till dig själv med vanliga misstag som (du) ofta görs. Titta t.ex. på denna som inspiration. Samla det du behöver dubbelkolla i en checklista, så blir det enklare att hålla koll! Du kan utgå från "Vanliga misstag" på HTML och CSS-kursen, och fortsätta att fylla på listan. Här har du ett exempelrepo på hur det kan se ut.
- Glöm inte att ändra dokumentets titel:
<title>Document</title> - Skriv utf-8 med gemener:
<meta charset="UTF-8">. Konvention är att använda "lowercase" (gemener) i HTML. - Sätt lang-attributet på html-taggen:
<html lang="sv">(eller vilket språk du nu använder).
Namngivning
Tänk på namngivningen av klasser i CSS och/eller funktioner i JavaScript. Håll dig till en standard. Undvik exempelvis att blanda camelCase och kebab-case, se Wikipedia t.ex. för definitioner.
Tillgänglighet
Glöm inte aria labels och liknande för att hålla koll på tillgängligheten, t.ex. om ni lägger ut information i HTML-dokumentet som bara är synligt "visuellt".
Exempelvis denna kod är inte tillgänglig för att visa ratings:
html
<span class="fa fa-star checked"></span>
<span class="fa fa-star checked"></span>
<span class="fa fa-star checked"></span>
<span class="fa fa-star-o"></span>
<span class="fa fa-star-o"></span>1
2
3
4
5
2
3
4
5
html
<div aria-description="Rated 3 out of 5">
<span class="fa fa-star checked"></span>
<span class="fa fa-star checked"></span>
<span class="fa fa-star checked"></span>
<span class="fa fa-star-o"></span>
<span class="fa fa-star-o"></span>
</div>1
2
3
4
5
6
7
2
3
4
5
6
7
📹 Se också Death to icon fonts
Om du skapar en knapp med ett ikon-typsnitt så kan du använda aria-label och aria-hidden för att göra det tillgängligt, se nedan:
html
<div class="product-image-slideshow">
<button class="go-left" id="goLeft" aria-label="Previous product image">
<span class="material-symbols-rounded" aria-hidden="true">arrow_circle_left</span>
</button>
</div>1
2
3
4
5
2
3
4
5
.gitignore
Du saknar en .gitignore-fil i ditt projekt (denna ska du alltid skapa i början och ha med).
Du har inte skapat en "mall-gitignore" till dig själv som du kan kopiera från befintliga projekt.
.DS_Store (Mac)
Lägg in en fil som heter .gitignore och lägg in .DS_Store i den.
Sass
Du har inte komprimerat din Sass-fil (det görs dock automatiskt med Vite, så är inte ett problem om du använder Vite).
Undvik åäö, mellanslag och versaler
Såväl i filnamn som variabelnamn som klassnamn.
Undvik också mellanslag i filnamn, t.ex. my image.jpg heter bättre om den heter my_image.jpg. Vissa webbläsare/servrar klarar inte av att visa bilder som innehåller mellanslag i filnamnet.
Mappar och (alla) filer bör alltid skrivas med gemener. Dvs. ändra t.ex. MinBild.jpg till minbild.jpg eller min_bild.jpg. Det är inte i sig en bugg att skriva med versaler, men vissa webbläsare gör skillnad på stora och små bokstäver, och då kan det bli strul med att ladda filer.
Datum
Tänk på var någonstans du skapar datum för/i if-satser. Om du t.ex. högst upp i ditt program skapar en variabel såhär:
js
const today = new Date();1
Och sedan i en funktion gör såhär (för att kolla om man ska få rabatt om det är en särskild dag):
js
function checkDiscount() {
if (today.getDay() === 1) {
// annan kod
}
}1
2
3
4
5
2
3
4
5
Om användaren låter webbläsarfönstret vara uppe t.ex. över ett dygn (så att fredag övergår till lördag exempelvis), så kommer man ändå att få fredagens rabatt då datumet inte genereras på nytt i funktionen, utan är samma som när webbsidan öppnades första gången.
Du kan lösa det genom att generera ett nytt datum:
js
function checkDiscount() {
const today = new Date(); // tidpunkten för när funktionen anropas
if (today.getDay() === 1) {
// annan kod
}
}1
2
3
4
5
6
2
3
4
5
6
PS! Du kan testa specialregler genom att skriva ett specifikt datum i koden, t.ex. const today = new Date('2024-12-13'); för att testa luciadagen.
Rätt datatyp
När du skapar objekt, tänk på att använda rätt datatyp för att underlätta för dig själv framöver. T.ex. om du har ett pris, skriv hellre enbart siffran, då du förmodligen behöver göra någon ändring för själva siffran vid ett senare tillfälle (t.ex. rabatt eller räkna ut en totalsumma). Jämför nedan:
javascript
const myDonut = {
price: '18 kr'
};
const myOtherDonut = {
price: 18,
};
// 50 % discount
console.log(myDonut.price * 0.5); // => NaN
console.log(myOtherDonut.price * 0.5); // => 91
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
Style:a ID istället för klass
Fortsätt använda klasser i stylingen och undvik att använda id:n. Kombinera hellre, exempelvis:
html
<div class="cart" id="cart"></div>1
css
.cart {
/* styling här */
}1
2
3
2
3
script-taggen längst ner
Det är praxis att ha script-taggen precis innan avslutande body-tagg:
html
<script src="main.js"></script>
</body>1
2
2
Då laddas scriptet in sist och sidan är tillgänglig/synlig för användaren. Det är också vanligt att script-taggen ligger precis innan body, vilket då gör det snabbt för en annan utvecklare att se var någonstans en inlänkning sker. Bra att följa praxis, alltså.
Om du av någon anledning inte kan ha det, lägg då till attributet defer så att scriptet inte blockerar inladdningen av resten av sidan:
html
<script src="main.js" defer></script>1
Vi vill ha så snabba och responsiva sidor som möjligt.
Anonyma funktioner
Undvik att använda anonyma funktioner. Det är inte så mycket att "men just här har jag bara 2 rader kod", utan snarare att det lätt blir en dålig vana, och vi vill inte lägga oss till med sådana (precis som vi inte ska använda ID för styling i CSS).
Det finns flera skäl till att inte använda anonyma funktioner, men två starka sådana är:
1. Man slipper läsa funktionens innehåll för att förstå vad funktionen gör. Jämför nedan:
javascript
button.addEventListener('click', (e) => {
const productId = Number(e.target.getAttribute('data-id'));
addProductToCart(productId, 1);
});1
2
3
4
2
3
4
javascript
button.addEventListener('click', addProductToCart);
function addProductToCart(e) {
const productId = Number(e.target.getAttribute('data-id'));
addProductToCart(productId, 1);
}1
2
3
4
5
6
2
3
4
5
6
Ovan exempel består av några enstaka rader kod, men om funktionen hade bestått av 10+ rader så hade det blivit bökigare att förstå vad som händer. Nu kan vi i exempel 2, direkt på rad 1, avgöra vad som kommer att hända när man klickar på knappen - utan att behöva läsa funktionens kod.
2. Minneshantering
Om vi kan återanvända funktioner, så blir våra applikationer/webbplatser mycket snabbare. Om vi t.ex. på en sida har 100 knappar, och använder en anonym klickfunktion - då får vi 100 identiska funktioner. Använder vi istället en namngiven funktion, då har vi bara 1 funktion.
javascript
const my100Buttons = document.querySelectorAll('.clickable-button-that-does-something');
my100Buttons.forEach(btn => {
btn.addEventListener('click', () => { // Här skapas SAMMA funktion på nytt 100 gånger
// do something cool
});
});1
2
3
4
5
6
2
3
4
5
6
En mer optimerad lösning:
javascript
const my100Buttons = document.querySelectorAll('.clickable-button-that-does-something');
my100Buttons.forEach(btn => {
btn.addEventListener('click', my100buttonsClickHandler); // Återanvänd samma funktion
});
function my100buttonsClickHandler() {
// do something cool
}1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
Obs! Det går bra att skapa funktioner såhär, dessa är inte anonyma då de lagras i en namngiven variabel:
javascript
const myFunction = () => {
// do something cool
};1
2
3
2
3
"Nackdelen" med att definiera en funktion som en variabel är att det inte går att anropa funktionen innan den är definierad:
javascript
myFunction(); // Fel: ReferenceError
const myFunction = () => {
// do something cool
};1
2
3
4
2
3
4
Använder vi oss av en deklarerad funktion så går det dock bra (detta pga. s.k. "hoisting"):
javascript
myFunction();
function myFunction() {
// do something cool
}1
2
3
4
2
3
4
Fördelen med en const-funktion är att den inte går att modifiera (den blir "immutable", även om det väldigt sällan sker att någon skulle modifiera en funktion…), samt tillgången till this. Att deklarera med function-nyckelordet har även fördelen att det blir en namngiven funktion, vilket gör felsökning enklare, medan en const-funktion görs om till en (anonym) bokstav. Mer här för den intresserade.
Arrow functions
Tänk på att en "arrow function" också är en anonym funktion om den används på ett sådant sätt:
javascript
someHTMLElement.addEventListener("change", () => {
// kod här…
});1
2
3
2
3
Skriv om ovan:
javascript
someHTMLElement.addEventListener("change", functionName);
function functionName() {
// kod här…
}1
2
3
4
5
2
3
4
5
Tips: Gruppera initiala funktioner
Ofta behöver man göra vissa saker "direkt när sidan laddas", typ skriva ut produkter och kanske visa/dölja vissa element. Ett tips är att skapa funktion som heter t.ex. init (förkortning för initialize), och gruppera funktionerna där - istället för att de ligger och flyter löst på diverse ställen i koden.
Jämför:
javascript
function printProducts() {
// …
}
printProducts();
// nån annan kod…
function showCardForm() {
// …
}
showCardForm();1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
javascript
function initApp() {
printProducts();
showCardForm();
}
// Längst ner i koden/dokumentet
initApp();1
2
3
4
5
6
7
2
3
4
5
6
7