Objekter tillader dig at gemme samlinger af værdier med nøgler. Det er fint.
Men meget ofte finder vi ud af, at vi har brug for en ordnet samling, hvor vi har et 1., et 2., et 3. element osv. For eksempel har vi brug for det til at gemme en liste over noget: brugere, varer, HTML-elementer osv.
Det er ikke praktisk at bruge et objekt her, fordi det ikke giver metoder til at håndtere rækkefølgen af elementer. Vi kan ikke indsætte en ny egenskab “mellem” de eksisterende. Objekter er bare ikke beregnet til sådan brug.
Der findes en speciel datastruktur kaldet Array, til at gemme ordnede samlinger.
Deklaration
Der er to syntakser til at oprette et tomt array:
let arr = new Array();
let arr = [];
Næsten altid bruges den anden syntaks. Vi kan angive startværdier i parenteserne:
let fruits = ["Apple", "Orange", "Plum"];
Array elementer er nummererede, startende fra nul.
Vi kan få et element ved dets nummer i firkantede parenteser:
let fruits = ["Æble", "Appelsin", "Blomme"];
alert( fruits[0] ); // Æble
alert( fruits[1] ); // Appelsin
alert( fruits[2] ); // Blomme
Vi kan erstatte et element:
fruits[2] = 'Pære'; // now ["Æble", "Appelsin", "Pære"]
…Eller tilføj en ny til arrayet:
fruits[3] = 'Citron'; // now ["Æble", "Appelsin", "Pære", "Citron"]
Det samlede antal elementer i arrayet er dets length:
let fruits = ["Æble", "Appelsin", "Blomme"];
alert( fruits.length ); // 3
Vi kan også bruge alert til at vise hele arrayet.
let fruits = ["Æble", "Appelsin", "Blomme"];
alert( fruits ); // Æble,Appelsin,Blomme
Et array kan gemme elementer af enhver type.
For eksempel, det kan være en blanding af værdier:
// blanding af værdier
let arr = [ 'Æble', { name: 'Karsten' }, true, function() { alert('hej'); } ];
// henter objektet ved indeks 1 og viser dets navn
alert( arr[1].name ); // Karsten
// henter funktionen ved indeks 3 og kører den
arr[3](); // hej
Et array, ligesom et objekt, kan ende med et komma:
let fruits = [
"Æble",
"Appelsin",
"Blomme",
];
Det “hængende komma” gør det lettere at indsætte/fjerne elementer, fordi alle linjer bliver ens.
Hente sidste elementer med “at”
Lad os sige, at vi vil have det sidste element i arrayet.
Nogle programmeringssprog tillader brugen af negative indekser til det samme formål, som fruits[-1].
Men i JavaScript virker det ikke. Resultatet vil være undefined, fordi indekset i firkantede parenteser behandles bogstaveligt.
Vi kan eksplicit beregne indekset for det sidste element og derefter få adgang til det: fruits[fruits.length - 1].
let fruits = ["Æble", "Appelsin", "Blomme"];
alert( fruits[fruits.length-1] ); // Blomme
En smule besværligt, ikke? Vi skal skrive variabelnavnet to gange.
Heldigvis findes der en kortere syntaks: fruits.at(-1):
let fruits = ["Æble", "Appelsin", "Blomme"];
// Samme som fruits[fruits.length-1]
alert( fruits.at(-1) ); // Blomme
Med andre ord, arr.at(i):
- er præcis det samme som
arr[i], hvisi >= 0. - for negative værdier af
i, går det baglæns fra slutningen af arrayet.
Metoderne pop/push, shift/unshift
En kø er en af de mest almindelige anvendelser af et array. I datalogi betyder det en ordnet samling af elementer, som understøtter to operationer:
pushtilføjer et element til slutningen.shifthenter et element fra begyndelsen, hvilket flytter køen frem, så det 2. element bliver det 1.
Arrays understøtter begge operationer.
I praksis har vi ofte brug for det. For eksempel en kø af beskeder, der skal vises på skærmen.
Der er en anden anvendelse af arrays – datastrukturen kaldet stak.
Den understøtter to operationer:
pushtilføjer et element til slutningen.pophenter et element fra slutningen.
Så nye elementer tilføjes eller tages altid fra “enden”.
En stak illustreres normalt som en bunke kort: nye kort tilføjes øverst eller tages fra øverst:
For stakke modtages det senest tilføjede element først, det kaldes også LIFO-princippet (Last-In-First-Out). For køer har vi FIFO (First-In-First-Out).
Arrays i JavaScript kan fungere både som en kø og som en stak. De tillader dig at tilføje/fjerne elementer både i starten og i slutningen. I datalogi kaldes datastrukturen, der tillader dette, for en deque.
Metoder, der arbejder med slutningen af arrayet:
pop-
Trækker det sidste element ud af arrayet og returnerer det:
let fruits = ["Æble", "Appelsin", "Blomme"]; alert( fruits.pop() ); // fjern "Blomme" og vis det alert( fruits ); // Æble, AppelsinBåde
fruits.pop()ogfruits.at(-1)returnerer det sidste element i arrayet, menfruits.pop()ændrer også arrayet ved at fjerne det. push-
Tilføjer elementet til slutningen af arrayet:
let fruits = ["Æble", "Appelsin"]; fruits.push("Blomme"); alert( fruits ); // Æble, Appelsin, BlommeKaldet
fruits.push(...)svarer tilfruits[fruits.length] = ....
Metoder, der arbejder med begyndelsen af arrayet:
shift-
Trækker det første element ud af arrayet og returnerer det:
let fruits = ["Æble", "Appelsin", "Blomme"]; alert( fruits.shift() ); // fjern "Æble" og vis det alert( fruits ); // Appelsin, Blomme unshift-
Tilføjer elementet til begyndelsen af arrayet:
let fruits = ["Appelsin", "Blomme"]; fruits.unshift('Æble'); alert( fruits ); // Æble, Appelsin, Blomme
Metoderne push og unshift kan tilføje flere elementer på én gang:
let fruits = ["Æble"];
fruits.push("Appelsin", "Blomme");
fruits.unshift("Ananas", "Citron");
// ["Ananas", "Citron", "Æble", "Appelsin", "Blomme"]
alert( fruits );
Intern opbygning
Et array er en særlig slags objekt. De firkantede parenteser, der bruges til at få adgang til en egenskab arr[0], stammer faktisk fra objektsyntaksen. Det er i bund og grund det samme som obj[key], hvor arr er objektet, mens tal bruges som nøgler.
De udvider objekter ved at tilbyde specielle metoder til at arbejde med ordnede samlinger af data og også length-egenskaben. Men i kernen er det stadig et objekt.
Husk, der kun er otte grundlæggende datatyper i JavaScript (se kapitlet Datatyper for mere info). Array er et objekt og opfører sig derfor som et objekt.
For eksempel kopieres det ved reference:
let fruits = ["Banan"]
let arr = fruits; // kopier ved reference (to variabler refererer til samme array)
alert( arr === fruits ); // true
arr.push("Pære"); // ændrer arrayet ved reference
alert( fruits ); // Banan, Pære - 2 elementer nu
…Men det, der virkelig gør arrays specielle, er deres interne repræsentation. Motoren forsøger at gemme elementerne i et sammenhængende hukommelsesområde, ét efter ét, som vist på illustrationerne i dette kapitel, og der er også andre optimeringer for at få arrays til at køre virkelig hurtigt.
Men de bryder alle sammen, hvis vi holder op med at arbejde med et array som en “ordnet samling” og begynder at arbejde med det, som om det var et almindeligt objekt.
For eksempel kan vi teknisk set gøre dette:
let fruits = []; // lav et array
fruits[99999] = 5; // tildel en egenskab med et indeks langt større end længden
fruits.age = 25; // opret en egenskab med et vilkårligt navn
Det er muligt, fordi arrays i bund og grund er objekter. Vi kan tilføje vilkårlige egenskaber til dem.
Men motoren vil se, at vi arbejder med arrayet som med et almindeligt objekt. Array-specifikke optimeringer er ikke egnede til sådanne tilfælde og vil blive slået fra, deres fordele forsvinder.
Måder at misbruge et array på:
- Tilføj en ikke-numerisk egenskab som
arr.test = 5. - Lav huller, som: tilføj
arr[0]og derefterarr[1000](og intet imellem). - Fyld arrayet i omvendt rækkefølge, som
arr[1000],arr[999]og så videre.
Tænk venligst på arrays som specielle strukturer til at arbejde med ordnede data. De tilbyder specielle metoder til det. Arrays er omhyggeligt optimeret i JavaScript-motorer til at arbejde med sammenhængende ordnede data, brug dem venligst på denne måde. Og hvis du har brug for vilkårlige nøgler, er chancerne store for, at du faktisk har brug for et almindeligt objekt {}.
Performance
Metoderne push/pop kører hurtigt, mens shift/unshift