Sign in
Up by karmicmind

Centrale elementer i JavaScript

Dette dokument beskriver de centrale elementer i JavaScript (duh!). Alle sammenligninger (=== eller !==) i kodeeksemplerne evaluerer til true.

Datatyper

I løbet af et JavaScript-programs kørsel bliver der oprettet, gemt, ændret, overført og returneret værdier (enkeltdele af data) af forskellige typer, kaldet data-typer, afhængig af naturen af det værdien skal repræsentere. Ud over de mere omfattende objekt-baserede datatyper (som f.eks. Date eller HTMLElement) eksisterer bl.a. følgende primitive datatyper i JavaScript.

Number

Numeriske værdier repræsenteres med datatypen Number. Disse værdier kan indgå i matematiske beregninger og bruges til at gemme f.eks. antal, størrelser, positioner, længder m.v.

42;       // Number værdier kan være heltal,
3.14;     // decimaltal,
NaN;      // ikke-tal og
Infinity; // uendelighed.

72 - 81 * 14 + 11 / 5 === -1059.8;  // Matematiske beregninger bliver udført
64 / ( -3 + 67 ) * 16 === 16;       // i henhold til regnearternes hieraki.

String

Tekst og andre sekvenser af skrifttegn repræsenteres som en streng. Disse værdier kan deles, konkateneres (lægges i forlængelse af hinanden) og transformeres på forskellig vis og bruges typisk til at gemme navne, beskeder, tilstande, links eller serialiserede repræsentationer af data af forskellige datatyper (f.eks. via JSON).

"Hej verden";                     // Strenge angives enten med dobbelt-
'Hej verden';                     // eller enkelt-anførselstegn.
"Tommy\'s giant \"deathray\"";    // Special-tegn citeres med backslash(\).
"Første linje.\nAnden linje.";
"C:\\Windows\\System32";
"Sm\u00e5 s\u00f8de jordb\u00e6r";  // Unicode.

"Smølfe" + "spark" === "Smølfespark";             // Konkatenering.
"Un-fucking-believable".substr(3, 4) === "fuck";  // Delstreng.
"big".toUpperCase() === "BIG";                    // Transformering.

Boolean

Binære eller boolske værdier kaldes for booleans. Disse indgår i logiske beregninger og kan bruges til at gemme hvorvidt en given egenskab er gældende eller ej. Betingede kodestumper angives typisk med et boolsk udtryk som parameter til en if-blok, while- eller for-løkke.

true; false;                // De eneste mulige værdier en boolean kan have.
(false && true) === false;  // Boolske beregninger.
(2 + 2 === 4) === true;     // Sammenligninger evaluerer til booleans.
!!(42) === true;            // Andre datatypers sandhedsværdi kan
!!("false") === true;       // konkretiseres til en boolean.

Null og Undefined

Variabler kan også have “tomme” ubetydelige “ikke-værdier” i JavaScript. Dette er typisk til variabler som endnu ikke har fået tildelt en værdi (undefined) eller med vilje er blevet tildelt en “tom” værdi fordi den af den ene eller anden grund er irrelevant eller ukendt (null).

var nyVariabel;                 // Alle variabler har værdien undefined
nyVariabel === undefined;       // indtil de har fået tildelt en værdi.

var meaningOfLife = null;   // Noget vi endnu ikke kender svaret på.

Array

En sekvens af værdier (af samme eller forskellige datatyper) kaldes et array. Her ligger værdierne gemt i pladser (index) numererede fra 0 og opefter. Til arrays kan man tilføje, fjerne, sortere og flytte værdier og bruges typisk til at gemme en samling af relaterede værdier eventuelt i en bestemt rækkefølge.

Teknisk set er arrays objekter i JavaScript og altså ikke en primitiv datatype, men det er nu ret grundlæggende at stifte kendskab med den alligevel.

var mitArray = [false, "to", 13];       // To måder at angive et nyt array.
mitArray = new Array("eins", 22, true);

mitArray[1] === 22;           // Index 1 ligger på 2. plads i arrayet.
mitArray.push("hurra");       // Tilføj til slutningen af arrayet.
mitArray.pop() === "hurra";   // Fjern sidste værdi og returnér det.
mitArray.shift() === "eins";  // Fjern første værdi, ryk alle elementer en
                              // plads ned og returnér værdien.

Object

Alle ikke-primitive data-typer er teknisk set objekter. Man kan bruge objekter til at definere sine egne data-typer (og typisk får man nogen forærende fra start, f.eks. Date), men man kan dog også bruge objekter i sin simpleste form (object literals) til at gemme navngivne egenskaber for ting.

var mitObj = { navn: "Tommy", alder: 32 };  // Oprettelse af object literal.
mitObj.navn === "Tommy";                    // Egenskaber kan tilgås direkte
mitObj["alder"] === 32;                     // eller som key.
mitObj.livret = "Sushi";                    // Nye egenskaber kan tilføjes.

Function

I modsætning til mange andre programmeringssprog kan man i JavaScript også betragte funktioner som en data-type. Dette gør det muligt at behandle funktioner på lige fod med andre data-type så man f.eks. kan overføre dem som parameter (f.eks. callbacks) til en anden funktion eller som retur-værdi (f.eks. eksportering til et højere scope).

typeof moms === "undefined";  // Navngivne funktioner bliver gemt før den
typeof slut === "function";   // øvrige kode bliver kørt.

var moms = function(pris) { // Funktioner kan tildeles som værdi til en
  return pris * 1.25;       // variabel.
};
typeof moms === "function";
moms(100) === 125;

function slut() {                   // Funktioner defineret med denne
  console.log("Så er tiden gået!"); // syntaks bliver gemt først.
}                                   // Funktionsnavnet kan tilgåes som
                                    // variabel.
setTimeout(slut, 15000);  // Funktioner kan angives som callback-parameter.

Funktioner

Vi kan gemme kodestumper, som vi ofte vil køre, i funktioner, således at vi altid kan køre flere linjers kode med en enkelt kald udefra. Funktioner kan eventuelt modtage parametre til f.eks. at bestemme nogen indstillinger for hvad koden gør. Funktioner kan også returnere et resultat til det sted i koden funktionen blev kaldt fra og f.eks. blive gemt i en variabel eller fodret som parameter til endnu et funktionskald eller blot indgå som en del af en større beregning.

function areal(bredde, hojde) {
  return bredde * hojde;
}

function rumfang(bredde, hojde, lengde) {
  return areal(bredde, hojde) * lengde;
}

function angivEnhed(storelse, enhed) {
  return storelse + " " + enhed;
}

console.log("Kassen fylder " + angivEnhed(rumfang(10, 20, 30), "cm^3"));

Variabler og variabel scope

Man kan gemme sine værdier i variabler, således at man henvise til dem ved navn. Ved objekter (og dermed også arrays og funktioner) gemmes dog kun en reference til det egentlige objekt. Dette gør det muligt for to variabler at gemme det samme objekt, således at ændringer i den ene variabel kan ses i den anden og omvendt.

var num1 = 1;
var num2 = num1;  // Primitive værdier bliver kopieret.
num2++;           // Ændringer til num2
num1 === 1;       // påvirker ikke num1.
num1 !== num2;    // Værdierne sammelignes.
num2 = 1;
num1 === num2;

var obj1 = { navn: "Tommy", alder: 32 };
var obj2 = obj1;    // Kun referencen bliver kopieret, ikke selve objektet.
obj2.alder++;       // Ændringer i obj2
obj1.alder === 33;  // påvirker også obj1.
obj1 === obj2;                        // Referencerne sammelignes, også
obj2 = { navn: "Tommy", alder: 32 };  // selvom objekterne indholdsmæssigt
obj1 !== obj2;                        // er identiske.

Variabler bør altid erklæres med var før de tages i brug. Dette er med til at bestemme indenfor hvilke scopes variablen kan tilgås. Variabler kan kun tilgås indenfor den funktion den er blevet erklæret i, herunder eventuelle under-funktioner. De kan altså ikke tilgås udefra.

var globalVar = "Keeng ov teh wurl!";
(function(){
  var iifeVar = "only in this script";

  globalVar = "Queen of hearts";

  function replaceRuler(newRuler) { // Parametre bliver automatisk erklæret
                                    // som lokale variabler.
    if (globalVar === "Queen of hearts") {
      globalVar = newRuler;
      iifeVar = "Revolution!";
    }
  }

  replaceRuler("Prince Charming");
  typeof newRuler === "undefined"; // Ikke tilgængelig.
  globalVar === "Prince Charming"; // Ændret af replaceRuler.
  iifeVar === "Revolution!";

})();
globalVar === "Prince Charming";
typeof iifeVar === "undefined";

Man kan også give sin variabel samme navn som en anden variabel på et højere scope-niveau uden at den anden variabel bliver overskrevet. Dette gør dog at man ikke længere tilgå den yderste variabel. JavaScript vælger altid den “nærmeste”.

var potato = "good";
(function(){
  potato === undefined; // Variabel erklæringer bliver kørt før den øvrige
                        // kode i funktionen. Derfor er den globale variabel
                        // utilgængelig allerede her.
  var potato = "bad";
  potato === "bad";   // Lokal variabel.
})();
potato === "good";    // Uændret.

Betingelser (conditions)

For at styre hvilke dele af koden der bliver kørt under hvilke omstændigheder kan vi bruge kontrol strukturen if. Her angiver vi en boolean eller boolsk udtryk, som bestemmer om den valgte kode skal køre eller (med else) om en eventuel alternativ kodestump skal køre i stedet.

var answer = prompt("Hvad er meningen med livet?");
if (answer == 42) {
  console.log("Hvor er du klog! ^_^");
} else if (answer == "Regnbueis!") {
  console.log("Det er flot, lille ven.. :p");
} else {
  console.log("Du ved da heller ikke noget som helst.. :(");
}

En alternativ kontrol struktur man kunne bruge, hvis betingelsen er baseret på værdien af et bestemt udtryk (f.eks. en bestemt variabel), er switch-cade. Her skal man blot huske break i slutningen af hvert udfald.

var answer = prompt("Hvad er meningen med livet?");
switch (answer) {
  case "42":
    console.log("Hvor er du klog! ^_^");
    break;
  case "Regnbueis!":
    console.log("Det er flot, lille ven.. :p");
    break;
  default:
    console.log("Du ved da heller ikke noget som helst.. :(");
}

Hvis man er lidt doven, kan man udnytte sandhedsværdien (truthiness) af ikke-boolske værdier. Udover false så betragtes værdierne null, undefined, 0 og "" som “falsy” og stort set alle andre værdier er “truthy”.

var response = prompt("Sig noget!");
if (response) {
  console.log("Det var godt.. :)");
} else {
  console.log("Du sagde jo ikke noget! :(");
}

Iterationer (while-løkker)

Hvis man vil have en del af koden til at gentage sig, kan man benytte sig af while. Princippet er nøjagtig det samme som med if, bortset fra at der ikke er nogen else og at koden bliver ved med at blive gentaget, så længe det betingende udtryk evaluerer til true (eller på anden vis er truthy).

while (prompt("Er vi der snart..??") !== "ja") {
  console.log("Øv.. :(");
}
alert("Yay..! ^_^");

En anden variant er do-while, hvor betingelses-tjekket først bliver udført efter hver iteration (i modsætning til før iterationerne). Dermed bliver løkken altid kørt mindst én gang.

do {
  console.log("Jeg bliver lige kørt en enkelt gang...");
} while (false);

Arrays og for-løkker

Løkker er især en fordel når vi skal behandle arrays. For at behandle hver enkelt værdi i arrayet, bliver vi nødt til at gentage noget kode for hvert index i arrayet. Vi sørger som regel for at erklære de variabler vi skal bruge i løkken udenfor løkken, så de ikke bliver ærklæret unødvendigt mange gange. Vi arbejder jo alligevel indenfor samme scope.

var friend, friends = [ "Alice", "Bob", "Carol" ];
var i = 0;
while (i < friends.length) {
  friend = friends[i];
  console.log(friend + " er hermed inviteret til min fødselsdag.. :)");
  i++;
}

Da denne type af iterationer er noget vi bruger tit, er der selvfølgelig en genvej. Vi kan bruge en for-løkke til at kortfatte initialiseringen og inkrementeringen af tælle-variablen i.

var friend, friends = [ "Alice", "Bob", "Carol" ];
for (var i = 0; i < friends.length; i++) {
  friend = friends[i];
  console.log(friend + " er hermed inviteret til min fødselsdag.. :)");
}