Komplexa variabler: Skillnad mellan sidversioner

Från Webbling
Hoppa till: navigering, sök
(Skapade sidan med 'Som man förstår av namnet går loopar runt på något vis. I den här betydelsen har man ett antal kodrader som repeteras, eller går i en loop, ett visst antal gånger. I p...')
 
Ingen redigeringssammanfattning
 
(23 mellanliggande sidversioner av samma användare visas inte)
Rad 1: Rad 1:
Som man förstår av namnet går loopar runt på något vis. I den här betydelsen har man ett antal kodrader som repeteras, eller går i en loop, ett visst antal gånger. I programmering brukar man kalla detta för iteration, vilket enbart är ett finare ord för upprepning.
Komplexa, eller sammansatta, variabler är en typ av variabler som kan innehålla flera olika värden.  Den vanligaste typ av sammansatta variabler är arrayer. Vilket är en typ av variabel där vi kan ange ett index för att tala om vilket värde vi vill komma åt.


Det finns flera olika typer av loopar att tillgå i JavaScript. Vi börjar med att gå igenom den vanligaste och mest användbara loop-typen; <code>while</code>-loopen.
Har du programmerat i något annat språk, t.ex. C#, kan det vara bra att veta att i JavaScript så är arrayer och listor ungefär samma sak. Arrayerna kan användas mer dynamiskt än i många andra språk.
== <code>while</code>-loop ==
<code>while</code>-loopen är den enklaste loop-typen. Den är både enkel att förstå samt att den är så generell att man egentligen skulle kunna klara sig med enbart denna typ av loop. Så om du enbart orkar lägga  en enda loop-typ på minnet, då är detta rätt val…


I grunden ser en <code>while</code>-loop ut så här:
== Skapa en array ==
En array skapas så här:
<syntaxhighlight lang="JavaScript">
let värden = [ 1, 2, 3, 4 ];
</syntaxhighlight>
 
I exemplet ovan skapas en array som innehåller fyra element. Elementen har värdena från <code>1</code> till <code>4</code>.
 
== Läsa ifrån en array ==
För att komma åt ett specifikt element i en array använder vi oss av <code>[</code>''index''<code>]</code>. Där ''index'' talar om vilket specifikt värde vi vill komma åt.  Ett exempel på detta.


<div class="well well-cyanide-light">
<syntaxhighlight lang="JavaScript">
<syntaxhighlight lang="JavaScript">
while ( liv > 0 )
let ettVärde = värden[0];
{
  <Denna kod upprepas tills antal liv blir noll eller mindre >
}
<Här fortsätter programmet när liv blir noll eller mindre>
</syntaxhighlight>
</syntaxhighlight>
</div>


På vanlig svenska skulle man säga; gör det här ''medan'' antal liv är större än noll. Så länge testvillkoret (kallas även för sanningsvillkoret) som man skickar till <code>while</code> är sant, kommer koden att upprepas. Men om villkoret är falskt, avslutas loopen och programmet fortsätter att köras från och med den kod som finns direkt efter loopen.
Ovanstående kod kommer att plocka ut det ''första'' värdet i arrayen. I programmering brukar vi oftast börja att räkna ifrån noll. Arrayen <code>värden</code> innehåller fyra element. Elementen är indexerade ifrån <code>0</code> till <code>3</code>. Sista elementet är alltså element nummer <code>3</code>, dvs ett mindre än antalet element. Detta är på grund av att vi räknar ifrån noll.
 
Vill vi ändra på innehållet i ett element, gör vi som ovan men med den skillnad att vi gör en tilldelning till elementet, t.ex.:
<syntaxhighlight lang="JavaScript">
värden[2] = 42;
</syntaxhighlight>


Om villkoret efter <code>while</code> är falskt redan när programmet når koden för första gången, kommer koden inuti loopen aldrig att köras. Om vi fortsätter med exemplet ovan och om antalet liv redan är noll, skulle programmet fortsätta att köra koden som kommer direkt efter <code>while</code>-satsen.
Liksom "vanliga" variabler, kan man ändra på datatypen vid en tilldelning.


== <code>do...while</code>==
== Gå igenom en array ==
Det finns en till variant av <code>while</code>-loopen. Skillnaden är att man sätter villkoret sist och påbörjar loopen med kommandot <code>do</code>.
Vi vill ofta gå igenom hela, eller delar av, arrayen och göra nåt med elementen som den innehåller. Det kan man göra på lite olika sätt...


<div class="well well-cyanide-light"><syntaxhighlight lang="JavaScript">
(Som vi kommer att se så är det lite skillnad på hur dessa två sätt beter sig)
do
{
  <Denna kod upprepas till antal liv når 0 >
} while ( liv > 0 );
</syntaxhighlight>
</div>


Den stora skillnaden mellan <code>while</code>-varianterna är var man testar om villkoret är sant. Eftersom <code>while</code>-kommandot kommer sist i denna variant, så kommer koden inom <code>do..while</code> att köras igenom ''minst'' en gång.
=== <code>for</code>-loop ===
<code>for</code>-loopar är en metod som vi kan använda oss av om vi vill gå igenom elementen i en array.


== Att räkna med <code>while</code>-loopar ==
Varje array har en egenskap som heter <code>length</code>, den är satt till det antal element som finns i arrayen. Genom att använda oss av <code>length</code> kan vi göra en <code>for</code>-loop på följande vis:
Egentligen är <code>for</code>-loopar mer lämpade  om man vill räkna, men vi kan göra det med hjälp av <code>while</code> också. Så här skulle man kunna göra;


<div class="well well-cyanide-light">
<syntaxhighlight lang="JavaScript">
<syntaxhighlight lang="JavaScript">
var a = 1;
for(let i = 0; i < värden.length; i++) {
while ( a < 5 )
  let ettVärde = värden[ i ];
{
  <Denna kod upprepas till antal a når 5 >


  a = a + 1
  console.log(ettVärde);
}
}
</syntaxhighlight>
</syntaxhighlight>
</div>


Exempelkoden skulle alltså räkna upp ifrån ett till fyra (eftersom vi kollar att <code>a</code> är ''mindre'' än fem).
I exemplet skriver vi alltså ut alla element i <code>värden</code>.
 
Lägg märke till att loopens test-del använder "<code>&lt;</code>", dvs loopen avslutas när den är ett steg under <code>length</code>. Vi konstaterade ju tidigare att elementen i arrayer indexeras ifrån <code>0</code> till och med <code>length - 1</code>. Vilket innebär att vi vill avsluta loopen ett steg under <code>length</code>.  När vi använder oss av <code>&lt;</code>, så avslutas loopen efter man nått sista elementet.


== <code>while</code> med grundvilkor ==
Då man kör en <code>for</code>-loop för att gå igenom arrayen, kan man använda sig av de vanliga <code>continue</code> och <code>break</code>. Vi kan alltså skippa steg och fortsätta med nästa element och vi kan bryta oss ur loopen helt och hållet. Det senare kan vara bra om vi t.ex. gjort allt som behöver göras och därmed inte behöver fortsätta igenom hela arrayen. Ett exempel på detta kunde vara att vi söker efter ett specifikt värde i arrayen, när vi hittar på det kanske vi vill bryta oss ur loopen istället för att gå igenom den helt och hållet.
Ofta sätter man ett startvärde eller ett grundvillkor strax innan man börjar sin loop, till exempel;
 
=== <code>forEach</code> ===
Ett annat sätt på vilket vi kan gå igenom en array är att använda oss av metoden <code>forEach</code>. Det är en metod som ingår i alla array-variabler. Vi anropar den genom att ange arraynamnet följt av <code>.forEach()</code>. <code>forEach</code> går igenom en array, element för element, och anropar en funktion för varje element.
 
Så här skulle föregående exempel bli att se ut om vi använder oss av <code>forEach</code> istället för en <code>for</code>-loop.


<div class="well well-cyanide-light">
<syntaxhighlight lang="JavaScript">
<syntaxhighlight lang="JavaScript">
var running = true;
function skrivUt(n) {
  console.log(n);
}


while ( running ) {
värden.forEach(skrivUt);
  <Denna kod upprepas till running blir false >
}
</syntaxhighlight>
</syntaxhighlight>
</div>


Inuti loop-koden har man sedan någonting som gör att <code>running</code> blir satt till <code>false</code> och då avslutas loopen nästa runda.
<code>forEach</code> plockar ut varje element var för sig. Varje element som plockas ut, kommer att skickas till funktionen <code>skrivUt</code>. Funktionen kommer att få det utplockade elementet som input, dvs <code>skrivUt</code>:s <code>n</code> kommer att sättas till ett element-värde.
 
I JavaScript behandlar man funktioner som "vanliga" variabler. Vi skickar <code>skrivUt</code> som parameter till <code>forEach</code> och eftersom den inte har <code>()</code> efter sig, så ses den som en variabel. Skulle vi haft <code>()</code> efter den, skulle funktionen körts direkt.


== <code>for</code>-loopar ==
Man kan ''inte'' använda sig av <code>break</code> eller <code>continue</code> med <code>forEach</code>.
<code>for</code>-loopar passar bäst när man redan från början vet att man ska göra något ett visst antal gånger eller räkna igenom en viss talföljd.


En <code>for</code>-loop ser i grunden ut så här
== Oväntade beteenden ==
Hur JavaScript hanterar arrayer kan ibland vara lite "konstigt". Vi ska gå igenom några exempel...


<div class="well well-cyanide-light">
===Läsa utanför arrayen===
<syntaxhighlight lang="JavaScript">
<syntaxhighlight lang="JavaScript">
for( var i=0; i < 10; i++ )
let värden = [ 1, 2, 3, 4 ];
{
 
  <Denna kod upprepas tio gånger>
console.log(värden[10]);
  <och i börjar som 0, räknas upp ett steg i taget och slutar som 9>
}
</syntaxhighlight>
</syntaxhighlight>
</div>


Man kan bryta ner for-satsen i tre delar:
Vår array innehåller ju bara fyra värden, men vi försöker komma åt det elfte (kom ihåg att vi räknar ifrån noll). Vi kommer inte att få ett felmeddelande, istället får vi värdet <code>undefined</code>. JavaScript bryr sig alltså inte om att vi är "utanför" den array vi definierat. Däremot har vi ju inte satt något värde i det angivna elementet och vi får därför tillbaka <code>undefined</code>, vilket ju stämmer.


<ol>
=== Skriva utanför arrayen ===
<li><code>var i=0</code>


Den så kallade initialiseringen. I det här fallet så skapar vi en variabel som vi ska använda för att räkna med och sätter den till noll. Loop-variabeln kallas oftast för loopindex. Vid <code>for</code>-loopens start sätts loopindex till startvärdet noll (det är det som kallas för initialisering), men man kunde förstås sätta den till vad som helst. Initialiseringen sker enbart vid uppstarten av loopen och den körs inte under de efterföljande varven. Man kan göra vad som helst vid initialiseringen, inte bara skapa variabler. Om man så vill kan man lämna initialiseringen helt tom.
Vad händer om vi gör följande:
</li>
<syntaxhighlight lang="JavaScript">
<li>
let värden = [ 1, 2, 3, 4 ];
<code>i < 10</code>


Detta är testvillkoret som avgör om man är klar med loopen eller ej. Denna koll körs varje loopvarv och det görs innan koden i loopen körs. Vi kan med andra ord köra koden noll eller flera gånger (till och med ett ”oändligt” antal gånger om vi så vill). Här kan man använda alla de booleska sanningsvillkoren om man så vill.
värden[10]=5;
</li>
<li><code>i++</code>


Slut-satsen, denna körs varje gång man kört klart ett loopvarv. I det här fallet ökar vi variabeln med ett (<code>++</code> är ett snabbare, kortare sätt att skriva <code>i = i + 1</code>). Efter att denna sats körts, går <code>for</code>-loopen tillbaka till början och genomför testvillkoret igen, programmet går alltså tillbaka till steg 2.
console.log(värden[10]);
</li>
</syntaxhighlight>
</ol>
Observera att loopen i exemplet kommer att köras tio gånger och kommer att räkna ifrån noll upp till nio.


Om man behöver kan man nästla loopar, dvs lägga loopar inuti andra loopar. T.ex;
I detta fall kommer koden att köras och vi får värdet <code>5</code> utskrivet. Vår array kommer alltså att göras större och bli att innehålla elva element. Men vad händer med de element som ligger på positionerna där vi inte angivit några värden? Vi provar:


<div class="well well-cyanide-light">
<syntaxhighlight lang="JavaScript">
<syntaxhighlight lang="JavaScript">
for( var i=0; i < 10; i++ )
let värden = [ 1, 2, 3, 4 ];
{
 
  for( var j=0; j < 10; j++ )
värden[10]=5;
  {
 
    <Denna kod upprepas tio * tio gånger (dvs, hundra gånger)>
console.log(värden[9]);
  }
}
</syntaxhighlight>
</syntaxhighlight>
</div>


== Kontrollkommandon för loopar ==
Vi får då utskriften <code>undefined</code>. Det blir ingen error, så elementet existerar. Men vi har inte satt det till något värde, därmed är det odefinierat.
=== <code>continue</code> ===
Det finns även några kommandon som kan användas inuti loopar för att styra hur loopen beter sig. Det första av dessa är <code>continue</code>. Om programmet befinner sig inuti en loop och kommer till en <code>continue</code>-instruktion, hoppar programmet över all efterföljande kod och går direkt till loop-satsens villkorssats.


Ett litet exempel:
==== Skillnad på <code>for</code>-loop och <code>forEach</code> ====
Om vi vill gå igenom alla element i arrayen,  så kommer vi i det här fallet att få olika resultat beroende på vilken loop-typ vi använder. Vi provar en <code>for</code>-loop först.


<div class="well well-cyanide-light">
<syntaxhighlight lang="JavaScript">
<syntaxhighlight lang="JavaScript">
for( var i=0; i < 10; i++ )
for(let i = 0; i < värden.length; i++) {
{
  let ettVärde = värden[ i ];
  if( isEven( i ) ) {
  console.log(ettVärde);
    continue;
  }
  <Denna kod körs bara när i är udda>
}
}
</syntaxhighlight>
</syntaxhighlight>
</div>


Varje gång <code>i</code> är ett jämt tal hoppar programmet över koden efter <code>if</code>:en. Det var alltså ett krångligt sätt att skriva något som vi lika gärna kunnat lösa genom att byta ut vår <code>i++</code> till <code>i += 2</code> (vilket är ett snabbare sätt att skriva <code>i = i + 2</code>).
Siffrorna 1-4 skrivs ut som vi förväntat oss. Därefter följer en del <code>undefined</code>, ända tills vi  når femman. Det var väl vad vi förväntat oss.


=== <code>break</code> ===
Nu provar vi med en <code>forEach</code>-loop istället.
Ett annat sätt att styra loopflödet är att använda sig av <code>break</code>. När programmet når en sådan instruktion avslutas nuvarande loop direkt och programmet fortsätter att köra den kod som följer efter loopen. Ett exempel på detta:


<div class="well well-cyanide-light">
<syntaxhighlight lang="JavaScript">
<syntaxhighlight lang="JavaScript">
while( true )
function SkrivUt(n) {
{
   console.log(n);
   if( pressedKey == ”q” ) {
    break;
  }
  <massvis med annan kod…>
}
}
<När man når break, hoppar koden direkt hit>


värden.forEach(SkrivUt);
</syntaxhighlight>
</syntaxhighlight>
</div>
 
Nu får vi enbart siffrorna 1-5 och vi ser inte något av de element vars värde är <code>undefined</code>. <code>forEach</code> skippar alltså över de element som inte är satta till något värde!

Nuvarande version från 30 juni 2021 kl. 12.00

Komplexa, eller sammansatta, variabler är en typ av variabler som kan innehålla flera olika värden. Den vanligaste typ av sammansatta variabler är arrayer. Vilket är en typ av variabel där vi kan ange ett index för att tala om vilket värde vi vill komma åt.

Har du programmerat i något annat språk, t.ex. C#, kan det vara bra att veta att i JavaScript så är arrayer och listor ungefär samma sak. Arrayerna kan användas mer dynamiskt än i många andra språk.

Skapa en array

En array skapas så här:

let värden = [ 1, 2, 3, 4 ];

I exemplet ovan skapas en array som innehåller fyra element. Elementen har värdena från 1 till 4.

Läsa ifrån en array

För att komma åt ett specifikt element i en array använder vi oss av [index]. Där index talar om vilket specifikt värde vi vill komma åt. Ett exempel på detta.

let ettVärde = värden[0];

Ovanstående kod kommer att plocka ut det första värdet i arrayen. I programmering brukar vi oftast börja att räkna ifrån noll. Arrayen värden innehåller fyra element. Elementen är indexerade ifrån 0 till 3. Sista elementet är alltså element nummer 3, dvs ett mindre än antalet element. Detta är på grund av att vi räknar ifrån noll.

Vill vi ändra på innehållet i ett element, gör vi som ovan men med den skillnad att vi gör en tilldelning till elementet, t.ex.:

värden[2] = 42;

Liksom "vanliga" variabler, kan man ändra på datatypen vid en tilldelning.

Gå igenom en array

Vi vill ofta gå igenom hela, eller delar av, arrayen och göra nåt med elementen som den innehåller. Det kan man göra på lite olika sätt...

(Som vi kommer att se så är det lite skillnad på hur dessa två sätt beter sig)

for-loop

for-loopar är en metod som vi kan använda oss av om vi vill gå igenom elementen i en array.

Varje array har en egenskap som heter length, den är satt till det antal element som finns i arrayen. Genom att använda oss av length kan vi göra en for-loop på följande vis:

for(let i = 0; i < värden.length; i++) {
   let ettVärde = värden[ i ];

   console.log(ettVärde);
}

I exemplet skriver vi alltså ut alla element i värden.

Lägg märke till att loopens test-del använder "<", dvs loopen avslutas när den är ett steg under length. Vi konstaterade ju tidigare att elementen i arrayer indexeras ifrån 0 till och med length - 1. Vilket innebär att vi vill avsluta loopen ett steg under length. När vi använder oss av <, så avslutas loopen efter man nått sista elementet.

Då man kör en for-loop för att gå igenom arrayen, kan man använda sig av de vanliga continue och break. Vi kan alltså skippa steg och fortsätta med nästa element och vi kan bryta oss ur loopen helt och hållet. Det senare kan vara bra om vi t.ex. gjort allt som behöver göras och därmed inte behöver fortsätta igenom hela arrayen. Ett exempel på detta kunde vara att vi söker efter ett specifikt värde i arrayen, när vi hittar på det kanske vi vill bryta oss ur loopen istället för att gå igenom den helt och hållet.

forEach

Ett annat sätt på vilket vi kan gå igenom en array är att använda oss av metoden forEach. Det är en metod som ingår i alla array-variabler. Vi anropar den genom att ange arraynamnet följt av .forEach(). forEach går igenom en array, element för element, och anropar en funktion för varje element.

Så här skulle föregående exempel bli att se ut om vi använder oss av forEach istället för en for-loop.

function skrivUt(n) {
  console.log(n);
}

värden.forEach(skrivUt);

forEach plockar ut varje element var för sig. Varje element som plockas ut, kommer att skickas till funktionen skrivUt. Funktionen kommer att få det utplockade elementet som input, dvs skrivUt:s n kommer att sättas till ett element-värde.

I JavaScript behandlar man funktioner som "vanliga" variabler. Vi skickar skrivUt som parameter till forEach och eftersom den inte har () efter sig, så ses den som en variabel. Skulle vi haft () efter den, skulle funktionen körts direkt.

Man kan inte använda sig av break eller continue med forEach.

Oväntade beteenden

Hur JavaScript hanterar arrayer kan ibland vara lite "konstigt". Vi ska gå igenom några exempel...

Läsa utanför arrayen

let värden = [ 1, 2, 3, 4 ];

console.log(värden[10]);

Vår array innehåller ju bara fyra värden, men vi försöker komma åt det elfte (kom ihåg att vi räknar ifrån noll). Vi kommer inte att få ett felmeddelande, istället får vi värdet undefined. JavaScript bryr sig alltså inte om att vi är "utanför" den array vi definierat. Däremot har vi ju inte satt något värde i det angivna elementet och vi får därför tillbaka undefined, vilket ju stämmer.

Skriva utanför arrayen

Vad händer om vi gör följande:

let värden = [ 1, 2, 3, 4 ];

värden[10]=5;

console.log(värden[10]);

I detta fall kommer koden att köras och vi får värdet 5 utskrivet. Vår array kommer alltså att göras större och bli att innehålla elva element. Men vad händer med de element som ligger på positionerna där vi inte angivit några värden? Vi provar:

let värden = [ 1, 2, 3, 4 ];

värden[10]=5;

console.log(värden[9]);

Vi får då utskriften undefined. Det blir ingen error, så elementet existerar. Men vi har inte satt det till något värde, därmed är det odefinierat.

Skillnad på for-loop och forEach

Om vi vill gå igenom alla element i arrayen, så kommer vi i det här fallet att få olika resultat beroende på vilken loop-typ vi använder. Vi provar en for-loop först.

for(let i = 0; i < värden.length; i++) {
   let ettVärde = värden[ i ];
   console.log(ettVärde);
}

Siffrorna 1-4 skrivs ut som vi förväntat oss. Därefter följer en del undefined, ända tills vi når femman. Det var väl vad vi förväntat oss.

Nu provar vi med en forEach-loop istället.

function SkrivUt(n) {
  console.log(n);
}

värden.forEach(SkrivUt);

Nu får vi enbart siffrorna 1-5 och vi ser inte något av de element vars värde är undefined. forEach skippar alltså över de element som inte är satta till något värde!