JS Studieclub - RayanSp/vervoerregio-amsterdam GitHub Wiki

You don't know JS yet

Week 1

23/05

Schermafbeelding 2024-02-05 om 11 54 02

"The best way to learn JS is to start writing JS." (Hoofdstuk 2)

Vandaag was de eerste club meeting! We gingen met een klein groepje het boek bespreken. In het boek informeert auteur Kyle Simpson de lezer over wat Javascript nou precies is en worden de basics uitgelegd. We gingen gezamenlijk door de hoofdstukken lezen en hebben hier veel van opgestoken.

Waarom heet het Javascript?

De naam Javascript is eigenlijk gewoon een marketing truc! Toen de bedenker Brendan Eich de taal bedacht had het project de code-naam Mocha. Maar toen de tijd kwam om een echte naam te kiezen werd er gekozen voor Javascript, waarom is dat? De initiële doelgroep was eigenlijk grotendeels Java programmeurs en het woord script was in die tijd een populair woord om te verwijzen naar light weight programma's.

"Quotation marks vs `back-ticks

Het gebruik van dubbele of enkelvoudige quotation marks maakt geen verschil voor de werking van je code. Wel is er een verschil in wat back-ticks doen. Hieronder heb ik een voorbeeld uit het boek gehaald. In onderstaand voorbeeld is te zien dat bij het gebruik van zowel dubbele als enkelvoudige quotation marks de string letterlijk overgenomen wordt. Bij het gebruik van back-ticks word de firstName variabel wel de value Kyle gegeven. (Dit heeft interpolation)

console.log("My name is ${ firstName }.");
// My name is ${ firstName }.
console.log('My name is ${ firstName }.');
// My name is ${ firstName }.
console.log(`My name is ${ firstName }.`);
// My name is Kyle.

Het verschil tussen var, let en const

Hieronder heb ik een voorbeeld uit het boek gehaald over het verschil tussen var en let. De name is hier een var en de age is hier een let. Zoals je kunt zien is alleen de name op te halen in de console.log en krijg je een error als je de age wilt weergeven. Waarom is dit? Een let is meer limited dan een var, dit heet block scoping. De let was geblock-scoped in de if statement terwijl de var dat niet is. Hierdoor kun je de var wel console.loggen buiten de if statement maar de let niet.

Dit klinkt als een nadeel maar dit kan ook erg handig zijn als je bijvoorbeeld meerdere variabelen hebt met dezelfde naamgeving. Je kunt deze dan block-scopen, zodat je ze niet door elkaar haalt.

var adult = true;
 
if (adult) {
    var name = "Kyle";
    let age = 39;
    console.log("Shhh, this is a secret!");
}
 
console.log(name);
// Kyle
 
console.log(age);
// Error!

We kunnen const natuurlijk niet vergeten! Een const is net als een let maar dan met nog een extra limitatie; je moet een const op declaratie een waarde geven en deze waarde kan je niet re-assignen.

Hieronder is een voorbeeld uit het boek te zien. Je kunt hier zien dat de const myBirthday een waarde krijgt van true bij declaratie. Er wordt geprobeerd de waarde van deze boolean hierna te re-assignen en dit kan niet met een const. Hier komt dus een error uit.

const myBirthday = true;
 
if (myBirthday) {
    myBirthday = false; // Error!
}

Een interessant kenmerk van const is dat je de waarde wel kunt veranderen, je kunt het alleen niet re-assignen. Wat betekent dit? Hieronder is een voorbeeld uit het boek te vinden. In onderstaand voorbeeld worden twee dingen geprobeerd.

Allereerst wordt actor[2] toegevoegd aan de array. Dit is een verandering aan de const die er niet voor zorgt dat een bestaande waarde in deze const ge re-assigned wordt aangezien er alleen een actor[0] en een actor[1] in de array zitten op declaratie. Dit kan!

In de tweede wijziging wordt er geprobeerd de data in de array te veranderen naar [] (niks dus, het wordt een lege array). Dit zou de waarden van actor[0] en actor[1] wijzigen en dus re-assignen. Dit kan niet!

const actors = [
    "Morgan Freeman", "Jennifer Aniston"
];
 
actors[2] = "Tom Cruise"; // OK :(
actors = []; // Error!

Week 2

30-5-2024

We gingen vandaag weer samenzitten voor de tweede Javascript club meeting. De nieuwe leden Ivar, Trisjan en Duneya deden vandaag ook mee. We gingen gezamelijk verder waar we vorige week gebleven waren. Deze week was wat technischer dan de vorige en dus wat moeilijker te begrijpen, maar doordat we elkaar constant hielpen en dingen aan elkaar uit aan het leggen waren tijdens het lezen zijn we er toch door gekomen.

Schermafbeelding 2024-02-05 om 11 54 02

Hoisting part 2

Ik ben er tijdens het schrijven van de week 2 notes achter gekomen dat hoisting wat dieper is dan ik eerst dacht. Hoisting werkt niet met let en const. Ze worden wel naar de top van de scope verplaatst maar komen terecht in een "temporal dead zone". Hoisting is dus alleen voor var en functie declaraties. Wel moet je erop letten dat deze twee soorten hoisting beide net iets anders werken.

Function hoisting vs Variable hoisting In onderstaande code heb ik het voorbeeld van hoisting part 1 gekopieerd. Hoisting met functies werkt gewoon zoals we al kennen. De functie declaratie wordt naar de top van de scope verplaatst en deze kun je hierna dus gewoon oproepen.

testFunctie();
// text

function testFunctie() {
    console.log("text");
}

Dit werkt echter net iets anders voor het hoisten van variabelen. In onderstaand voorbeeld probeer ik de var x te console loggen voordat deze gedeclareerd is net zoals ik deed in het function hoisting voorbeeld hierboven. Dit werkt echter niet in dit geval. Dit komt omdat alleen de declaratie van de variabel wordt gehoist, niet de initialisatie.

console.log(x) // undefined

var x = 1;

Wat betekent dit? Declaratie is het maken van de variabel, initialisatie is het geven van een waarde aan deze variabel. In onderstaand voorbeeld is de declaratie dus 'var x;' en is de initialisatie 'x = 1;'. Zoals eerder gezegd wordt alleen de declaratie gehoist en niet de initialisatie. Je moet er dus voor zorgen dat de initialisatie al bovenaan staat want deze zal niet voor je verplaatst worden.

In het bovenstaande voorbeeld worden de declaratie en de initialisatie in dezelfde regel gedaan. Omdat alleen de declaratie gehoist wordt zorgt dit ervoor dat er geen initialisatie is op het moment dat de console.log aangeroepen wordt. De x waarde is dus niet geinitialiseerd en is dus undefined. In het onderstaande voorbeeld heeft de x wel een waarde omdat de initialisatie bovenaan de scope staat geschreven en de declaratie naar de top van de scope gehoist wordt.

x = 1; (initialisatie)

console.log(x) // 1

var x; (declaratie)

Andere vormen van declaratie Naast de bekende var, let en const zijn er ook andere syntax die variabelen declareren. Voorbeelden hiervan zijn function en catch.

In onderstaand voorbeeld uit het boek is te zien dat function de identifier (voor een uitleg van wat een identifier is lees door) 'hello' declareerd met de parameter name. Een parameter is eigenlijk een local variable in de functie. Deze parameter bestaat alleen in de functie waarin hij gemaakt is en zal dus alleen bruikbaar zijn in de functie hello. We hebben bij de let uitleg van week 1 al eerder gehoord van block scoping en hier gebeurd bijna hetzelfde, nu is het echter function scoping omdat het in een functie gebeurt. De identifier hello zal zich daarintegen voordoen alsof het gedeclareerd werd in een var en is wel overal bruikbaar.

function hello(name) {
     console.log(`Hello, ${ name }.`);
}

hello("Kyle");
// Hello, Kyle.

In nog een voorbeeld uit het boek hieronder is te zien dat catch het variabel 'err' declareerd. Dit variabel is block scoped en bestaat alleen in de catch. Net alsof het door een let gedeclareerd was.

try {
    someError();
}

catch (err) {
    console.log(err);
}

Identifiers vs Variables In het 'Andere vormen van declaratie' gedeelte gebruik ik opeens het woord identifier maar wat is dit nou eigenlijk? Het boek legt dit niet goed genoeg uit maar ik heb hier zelf wat onderzoek naar gedaan. het verschil tussen identifiers en variables is heel vaag en onbelangrijk en je kunt dit stuk eigenlijk gewoon negeren maar als je het toch wilt weten lees door I guess.

Het verschil tussen identifiers en variables is ongeveer hetzelfde als het verschil tussen namen en mensen. In onderstaand voorbeeld is 'totaal' de identifier van de variable die de totale waarden van x + y bevat. Het is basically hetzelfde, maar het is dus ongeveer de naam van de variabel die de waarde bevat. De naam van de persoon. De persoon en zijn naam zijn hetzelfde maar eigenlijk anders als je begrijpt wat ik bedoel. Jij bent je naam niet, je naam is een identifier van jou als persoon. Ook al zijn ze beide hetzelfde.

let x = 5;
let y = 10;
let totaal = x + y;
Functions
We zijn al bekend met functions declarations zoals het voorbeeld hieronder.

function add(a, b) {
  return a + b;
}

console.log(add(2, 3)); // Outputs: 5

Hiernaast heb je ook dingen genaamd function expressions. In het voorbeeld hieronder is de function expression met de identifier 'function' te zien die geassigned is aan de const add.

const add = function(a, b) {
  return a + b;
};

console.log(add(2, 3)); // Outputs: 5

Zoals je ziet werken ze beide gewoon hetzelfde. Waarom zou ik dan ooit een function expression gebruiken?

Hieronder zijn een paar verschillen:

Function expressions worden niet gehoist (function declarations wel). Dit kan handig zijn om code beperkt te houden in een specifiek gedeelte van je code. Function expressions laten je functies toevoegen aan variabelen. Function expressions zorgen ervoor dat je functies kunt maken voor eenmalig gebruik. Ik ga een voorbeeld laten zien van hoe eenmalige functies zouden werken met function expressions omdat dat me een erg handig voordeel lijkt.

Hieronder is hoe je een message zou maken met een normale function declaration. Je moet helemaal een showMessage functie aanmaken die je maar 1x gaat gebruiken.

function showMessage() {
  console.log("Dit bericht verschijnt na 2 seconden");
}

setTimeout(showMessage, 2000);

Hieronder is hoe je een message zou maken met een function expression. Je hoeft de functie niet eens een naam te geven en zal hem hierna nooit meer gebruiken.

setTimeout(function() {
  console.log("Dit bericht verschijnt na 2 seconden");
}, 2000);

Comparisons

Single-equals zijn er om waarden aan variabelen te geven.

var x = 5;

Double-equals worden gebruikt voor een vergelijking met 'loose-equality'. Deze vergelijking is zoals de naam aanduidt niet heel strict. Er worden veel dingen achter de schermen gedaan zoals onder anderen het converten van strings naar numbers en true naar 1 (false naar 0). Hierdoor kunnen veel fouten voorkomen doordat soortgelijke waarden gezien worden als hetzelfde.

42 == "42"; // true
1 == true; // true
===

Triple-equals worden gebruikt voor een vergelijking met 'strict-equality'. Deze vergelijking is juist wel strict. Er zal hier niks geconvert worden achter de schermen en de waarden moeten dus gelijk zijn aan elkaar.

42 === "42"; // false
1 === true; // false

Er zijn twee special cases met deze strict equality comparisons. NaN (Not a Number) word niet als equal gezien met NaN en 0 wordt gezien als een equal van -0.

NaN === NaN; // false
0 === -0; // true
====

Om deze special cases te voorkomen kan gebruik gemaakt worden van de meest stricte versie van vergelijking, Object.is(). Een vergelijking met Object.is zal niet kijken of twee waarden gelijk zijn aan elkaar zoals de vorige comparisons. Object.is() zal kijken of de twee waarden hetzelfde zijn. Door deze strictheid kun je Object.is() zien als een quadruple-equals.

console.log(Object.is(NaN, NaN)); // true

console.log(Object.is(-0, 0)); // false For loops Voor het loopen van functies kun je een for loop gebruiken. Hierin kun je zelf bepalen hoeveel iteraties er zullen zijn door condities te bepalen waar de loop aan moet voldoen. Dit is handig voor een situatie waarin je een functie wilt blijven loopen tot een conditie niet meer klopt. Hieronder is een voorbeeld van een for loop uit het boek te vinden waarin een for loop 3 keer zal runnen.

De let i is standaard 0 Zolang de waarde van i lager is dan de lengte van de array (in dit geval 4) zal de loop doorgaan. Zolang de huidige waarde van arr lager is dan 500 zal de loop doorgaan. Dit is dus zolang i kleiner is dan 3 met de waarden in deze array. Elke keer dat de condities kloppen zal de waarde van i + 1 gaan. Eerste iteratie:

i = 0 De lengte van de array is 4, 0 < 4 De huidige waarde van arr is nu 1 (i = 0), 1 < 500 Eerste iteratie compleet, i++ (i is nu 1) Tweede iteratie:

i = 1 De lengte van de array is 4, 1 < 4 De huidige waarde van arr is nu 10 (i = 1), 10 < 500 Tweede iteratie compleet, i++ (i is nu 2) Derde iteratie:

i = 2 De lengte van de array is 4, 2 < 4 De huidige waarde van arr is nu 100 (i = 2), 100 < 500 Derde iteratie compleet, i++ (i is nu 3) Vierde iteratie:

i = 3 De lengte van de array is 4, 3 < 4 De huidige waarde van arr is nu 1000 (i = 3), 1000 > 500 Vierde iteratie niet gelukt, 1000 > 500 Deze for loop runt 3 keer dus.

var arr = [ "1", "10", "100", "1000" ];

for (let i = 0; i < arr.length && arr[i] < 500; i++) {
    // will run 3 times
}

Relational comparison Naast = kent iedereen < en >. Kleiner dan en groter dan natuurlijk. Je kunt deze combineren in een <= en >= (kleiner dan of gelijk aan/groter dan of gelijk aan)

1 > 0 1 < 2

1 <= 1 1 <= 2

1 >= 1 1 >= 0 Simpel toch? In het geval van vergelijking met relational operators tussen twee strings kunnen echter rare dingen gebeuren. In onderstaand voorbeeld uit het boek is te zien dat y (9) groter dan x (10) is.

Hoe komt dit? In het geval van vergelijking tussen twee strings met relational operators zal er alleen gekeken worden naar het eerste karakter in de string. In dit geval zal er dus een vergelijking plaatsvinden tussen de unicode waarden van 1 (49) en 9 (57). 49 < 57 en hierdoor zal x < y dus true zijn.

var x = "10";
var y = "9";

x < y; // true, watch out!
⚠️ **GitHub.com Fallback** ⚠️