[ Web Proxy ]
URL:
Viewing: https://da.javascript.info/array-methods [Back]  [Original]

Array-metoder
DA

Vi nsker at gre dette open source-projekt tilgngeligt for folk over hele verden.

Hjlp med at overstte indholdet af denne tutorial til dit sprog!

    Sg p Javascript.info:
    Sg i tutorialen:
    Lyst temaMrkt tema
    DanskEnglishEspaolFranaisIndonesiaItalianoTrkeOzbek

    Array-metoder

    Array giver os mange metoder. For at gre det nemmere, er de i dette kapitel opdelt i grupper.

    Tilfj/fjern elementer

    Vi kender allerede metoder, der tilfjer og fjerner elementer fra begyndelsen eller slutningen:

    • arr.push(...items) tilfjer elementer til slutningen,
    • arr.pop() fjerner et element fra slutningen,
    • arr.shift() fjerner et element fra begyndelsen,
    • arr.unshift(...items) tilfjer elementer til begyndelsen.

    Her er et par andre.

    splice

    Hvordan sletter man et element fra arrayet?

    Array er objekter, s vi kan prve at bruge delete:

    let arr = ["Jeg", "gr", "hjem"];
    
    delete arr[1]; // fjern "gr"
    
    alert( arr[1] ); // undefined
    
    // nu er  arr = ["Jeg",  , "hjem"];
    alert( arr.length ); // 3

    Elementet blev slettet, men har stadig 3 elementer. Vi kan se, at arr.length == 3.

    Det er naturligt, fordi delete obj.key fjerner en vrdi ved key. Det er alt, hvad det gr. Fint for objekter. Men for arrays nsker vi normalt, at resten af elementerne skal skifte og optage det frigjorte sted. Vi forventer at have et kortere array nu.

    Derfor skal der bruges specielle metoder.

    Metoden arr.splice er en schweizerkniv for arrays. Den kan det hele: indstte, fjerne og erstatte elementer.

    Syntaksen er:

    arr.splice(start[, deleteCount, elem1, ..., elemN])

    Den ndrer arr startende fra indekset start: fjerner deleteCount elementer og indstter derefter elem1, ..., elemN p deres plads. Returnerer arrayet af fjernede elementer.

    Metoden er nok nemmere at forst ved hjlp af eksempler.

    Lad os starte med sletning:

    let arr = ["Jeg", "studerer", "JavaScript"];
    
    arr.splice(1, 1); // fra indeks 1 fjern 1 element
    
    alert( arr ); // ["Jeg", "JavaScript"]

    Nem, ikke? Fra indeks 1 fjernede den 1 element.

    I det nste eksempel fjerner vi 3 elementer og erstatter dem med de to andre:

    let arr = ["Jeg", "studerer", "JavaScript", "lige", "nu"];
    
    // fjerner de 3 frste elementer og erstatter dem med andre
    arr.splice(0, 3, "Lad", "os", "danse");
    
    alert( arr ) // nu ["Lad", "os", "danse", "lige", "nu"]

    Her kan vi se, at splice returnerer arrayet af fjernede elementer:

    let arr = ["Jeg", "studerer", "JavaScript", "lige", "nu"];
    
    // fjern de 2 frste elementer
    let removed = arr.splice(0, 2);
    
    alert( removed ); // "Jeg", "studerer" <-- array af fjernede elementer

    Metoden splice kan ogs indstte elementer uden at fjerne nogen. For det skal vi stte deleteCount til 0:

    let arr = ["Jeg", "studerer", "JavaScript"];
    
    // fra indeks 2
    // slet 0
    // indst "et", "kompleks" og "sprog"
    arr.splice(2, 0, "et", "kompleks", "sprog");
    
    alert( arr ); // "Jeg", "studerer", "kompleks", "sprog", "JavaScript"
    Negative indeks er tilladt

    Her og i andre array-metoder er negative indekser tilladt. De angiver positionen fra slutningen af arrayet, som her:

    let arr = [1, 2, 5];
    
    // fra indeks -1 (et skridt fra slutningen)
    // slet 0 elementer,
    // indst derefter 3 og 4
    arr.splice(-1, 0, 3, 4);
    
    alert( arr ); // 1,2,3,4,5

    slice

    Metoden arr.slice er meget enklere end den lignende arr.splice.

    Syntaksen er:

    arr.slice([start], [end])

    Den returnerer et nyt array, der kopierer alle elementer fra indeks start til end (eksklusiv end). Bde start og end kan vre negative, i s fald antages positionen fra slutningen af arrayet.

    Det ligner string-metoden str.slice, men i stedet for substrings laver den subarrays.

    For eksempel:

    let arr = ["t", "e", "s", "t"];
    
    alert( arr.slice(1, 3) ); // e,s (kopier fra 1 til 3)
    
    alert( arr.slice(-2) ); // s,t (kopier fra -2 til slutningen)

    Vi kan ogs kalde den uden argumenter: arr.slice() laver en kopi af arr. Det bruges ofte til at f en kopi til videre transformationer, der ikke skal pvirke det oprindelige array.

    concat

    Metoden arr.concat opretter et nyt array der inkluderer vrdierne fra andre arrays og eventuelle yderligere elementer.

    Syntaksen er:

    arr.concat(arg1, arg2...)

    Den accepterer et vilkrligt antal argumenter enten arrays eller vrdier.

    Resultatet er et nyt array, der indeholder elementer fra arr, derefter arg1, arg2 osv.

    Hvis et argument argN er et array, kopieres alle dets elementer. Ellers kopieres argumentet selv.

    For eksempel:

    let arr = [1, 2];
    
    // Opret et array fra: arr og [3,4]
    alert( arr.concat([3, 4]) ); // 1,2,3,4
    
    // Opret et array fra: arr og [3,4] og [5,6]
    alert( arr.concat([3, 4], [5, 6]) ); // 1,2,3,4,5,6
    
    // Opret et array fra: arr og [3,4], og tilfj derefter vrdierne 5 og 6
    alert( arr.concat([3, 4], 5, 6) ); // 1,2,3,4,5,6

    Normalt kopierer den kun elementer fra arrays. Andre objekter, selvom de ligner arrays, tilfjes som helhed:

    let arr = [1, 2];
    
    let arrayLike = {
      0: "noget",
      length: 1
    };
    
    alert( arr.concat(arrayLike) ); // 1,2,[object Object]

    Men hvis et array-lignende objekt har en speciel Symbol.isConcatSpreadable egenskab, behandles det som et array af concat: dets elementer tilfjes i stedet:

    let arr = [1, 2];
    
    let arrayLike = {
      0: "noget",
      1: "andet",
      [Symbol.isConcatSpreadable]: true,
      length: 2
    };
    
    alert( arr.concat(arrayLike) ); // 1,2,noget,andet

    Iteration: forEach

    Metoden arr.forEach tillader at kre en funktion for hvert element i arrayet.

    Syntaksen er:

    arr.forEach(function(item, index, array) {
      // ... gr noget med elementet
    });

    For eksempel, dette viser hvert element i arrayet:

    // for hvert element kald alert
    ["Bilbo", "Gandalf", "Nazgul"].forEach(alert);

    Og denne kode er mere detaljeret om deres positioner i ml-arrayet:

    ["Bilbo", "Gandalf", "Nazgul"].forEach((item, index, array) => {
      alert(`${item} er ved indeks ${index} i ${array}`);
    });

    Resultatet af funktionen (hvis den returnerer noget) kasseres og ignoreres.

    Sgning i array

    Lad os nu dkke metoder, der sger i et array.

    indexOf/lastIndexOf og includes

    Metoderne arr.indexOf og arr.includes har en lignende syntaks og gr stort set det samme som deres string-modstykker, men opererer p elementer i stedet for tegn:

    • arr.indexOf(item, from) leder efter item startende fra indeks from, og returnerer indekset hvor det blev fundet, ellers -1.
    • arr.includes(item, from) leder efter item startende fra indeks from, returnerer true hvis fundet.

    Normalt bruges disse metoder med kun t argument: det item der skal sges efter. Som standard er sgningen fra starten.

    For eksempel:

    let arr = [1, 0, false];
    
    alert( arr.indexOf(0) ); // 1
    alert( arr.indexOf(false) ); // 2
    alert( arr.indexOf(null) ); // -1
    
    alert( arr.includes(1) ); // true

    Bemrk, at indexOf bruger streng lighed === til sammenligning. S hvis vi leder efter false, finder den prcis false og ikke nul.

    Hvis vi vil tjekke, om item findes i arrayet og ikke har brug for indekset, er arr.includes at foretrkke.

    Metoden arr.lastIndexOf er den samme som indexOf, men sger fra hjre mod venstre.

    let fruits = ['ble', 'Appelsin', 'ble']
    
    alert( fruits.indexOf('ble') ); // 0 (frste ble)
    alert( fruits.lastIndexOf('ble') ); // 2 (sidste ble)
    Metoden includes hndterer NaN korrekt

    En lille, men bemrkelsesvrdig funktion ved includes er, at den korrekt hndterer NaN, i modstning til indexOf:

    const arr = [NaN];
    alert( arr.indexOf(NaN) ); // -1 (forkert, burde vre 0)
    alert( arr.includes(NaN) );// true (korrekt)

    Dette er fordi includes blev tilfjet til JavaScript meget senere og bruger den mere opdaterede sammenligningsalgoritme internt.

    find og findIndex/findLastIndex

    Forestil dig, at vi har et array af objekter. Hvordan finder vi et objekt med en bestemt betingelse?

    Her kommer metoden arr.find(fn) til hjlp.

    Syntaksen er:

    let result = arr.find(function(item, index, array) {
      // hvis true returneres, returneres item og iterationen stoppes
      // for falsy scenarier returneres undefined
    });

    Funktionen kaldes for elementer i arrayet, et efter et:

    • item er elementet.
    • index er dets indeks.
    • array er selve arrayet.

    Hvis det returnerer true, stoppes sgningen, og item returneres. Hvis intet findes, returneres undefined.

    For eksempel, vi har et array af brugere, hver med felterne id og name. Lad os finde den med id == 1:

    let users = [
      {id: 1, name: "John"},
      {id: 2, name: "Pete"},
      {id: 3, name: "Mary"}
    ];
    
    let user = users.find(item => item.id == 1);
    
    alert(user.name); // John

    I virkelige projekter er arrays af objekter en almindelig ting, s find-metoden er meget nyttig.

    Bemrk, at i eksemplet giver vi kun t argument til find funktionen item => item.id == 1. Det er typisk, andre argumenter til denne funktion bruges sjldent.

    Metoden arr.findIndex har samme syntaks, men returnerer indekset hvor elementet blev fundet i stedet for elementet selv. Vrdien -1 returneres hvis intet findes.

    Metoden arr.findLastIndex er som findIndex, men sger fra hjre mod venstre, ligesom lastIndexOf.

    Her er et eksempel:

    let users = [
      {id: 1, name: "John"},
      {id: 2, name: "Pete"},
      {id: 3, name: "Mary"},
      {id: 4, name: "John"}
    ];
    
    // Find indeks med den frste John
    alert(users.findIndex(user => user.name == 'John')); // 0
    
    // Find indeks med den sidste John
    alert(users.findLastIndex(user => user.name == 'John')); // 3

    filter

    Metoden find sger efter et enkelt (frste) element der fr funktionen til at returnere true.

    Hvis der kan vre mange, kan vi bruge arr.filter(fn).

    Syntaksen er lignende find, men filter returnerer et array af alle matchende elementer:

    let results = arr.filter(function(item, index, array) {
      // hvis true bliver item tilfjet til results, og iterationen fortstter
      // returnerer et tomt array hvis intet findes
    });

    For eksempel:

    let users = [
      {id: 1, name: "John"},
      {id: 2, name: "Pete"},
      {id: 3, name: "Mary"}
    ];
    
    // returnerer et array med de frste to brugere
    let someUsers = users.filter(item => item.id < 3);
    
    alert(someUsers.length); // 2

    Transformr et array

    Lad os g videre til metoder, der transformerer og omarrangerer et array.

    map

    Metoden arr.map er en af de mest nyttige og ofte brugte.

    Den kalder funktionen for hvert element i arrayet og returnerer arrayet af resultater.

    Syntaksen er:

    let result = arr.map(function(item, index, array) {
      // returner den nye vrdi i stedet for item
    });

    For eksempel, her transformerer vi hvert element til dets lngde:

    let lengths = ["Bilbo", "Gandalf", "Nazgul"].map(item => item.length);
    alert(lengths); // 5,7,6

    sort(fn)

    Kaldet til arr.sort() sorterer arrayet i sig selv, og ndrer dermed rkkeflgen af dets egne elementer.

    Det returnerer ogs det sorterede array, men den returnerede vrdi ignoreres normalt, da arr selv bliver ndret.

    For eksempel:

    let arr = [ 1, 2, 15 ];
    
    // metoden omarrangerer indholdet af arr
    arr.sort();
    
    alert( arr );  // 1, 15, 2

    Bemrkede du noget mrkeligt i resultatet?

    Rkkeflgen blev 1, 15, 2. Forkert. Men hvorfor?

    Elementerne sorteres som standard som tekststrenge (string).

    Det betyder at alle elementer konverteres til strenge for sammenligninger. For strenge anvendes leksikografisk orden, og faktisk er "2" > "15".

    For at bruge vores egen sorteringsorden skal vi levere en funktion som argument til arr.sort().

    Funktionen skal sammenligne to vilkrlige vrdier og returnere:

    function compare(a, b) {
      if (a > b) return 1; // hvis den frste vrdi er strre end den anden
      if (a == b) return 0; // hvis vrdierne er lige
      if (a < b) return -1; // hvis den frste vrdi er mindre end den anden
    }

    For eksempel kan vi sortere som tal sledes:

    function compareNumeric(a, b) {
      if (a > b) return 1;
      if (a == b) return 0;
      if (a < b) return -1;
    }
    
    let arr = [ 1, 2, 15 ];
    
    arr.sort(compareNumeric);
    
    alert(arr);  // 1, 2, 15

    Nu virker det som forventet.

    Lad os trde et skridt tilbage og tnke over, hvad der sker. arr kan vre et array af hvad som helst, ikke? Det kan indeholde tal eller strenge eller objekter eller hvad som helst. Vi har et st af nogle elementer. For at sortere det, har vi brug for en ordensfunktion, der ved, hvordan man sammenligner dets elementer. Standard er en strengorden.

    Metoden arr.sort(fn) implementerer en generisk sorteringsalgoritme. Vi behver ikke bekymre os om, hvordan den internt fungerer (en optimeret quicksort eller Timsort det meste af tiden). Den vil g igennem arrayet, sammenligne dets elementer ved hjlp af den angivne funktion og omarrangere dem, alt hvad vi behver er at levere fn, som gr sammenligningen.

    Forresten, hvis vi nogensinde vil vide, hvilke elementer der sammenlignes intet forhindrer os i at vise dem med alert:

    [1, -2, 15, 2, 0, 8].sort(function(a, b) {
      alert( a + " <> " + b );
      return a - b;
    });

    Algoritmen kan sammenligne et element med flere andre i processen, men den prver at lave s f sammenligninger som muligt.

    En sammenligningsfunktion kan returnere et hvilket som helst tal

    Faktisk krves det kun, at en sammenligningsfunktion returnerer et positivt tal for at angive strre og et negativt tal for at angive mindre.

    Det tillader os at skrive kortere funktioner:

    let arr = [ 1, 2, 15 ];
    
    arr.sort(function(a, b) { return a - b; });
    
    alert(arr);  // 1, 2, 15
    Arrow funktioner for de vede

    Husk arrow functions? Vi kan bruge dem her for en pnere sortering:

    arr.sort( (a, b) => a - b );

    Det virker prcis p samme mde som den lngere version ovenfor.

    Brug localeCompare til strenge

    Husk du strings sammenligningsalgoritmen? Den sammenligner bogstaver efter deres koder som standard.

    For mange alfabeter er det bedre at bruge metoden str.localeCompare for korrekt at sortere bogstaver, ssom og , og .

    For eksempel, lad os sortere nogle lande p tysk:

    let countries = ['sterreich', 'Andorra', 'Vietnam'];
    
    alert( countries.sort( (a, b) => a > b ? 1 : -1) ); // Andorra, Vietnam, sterreich (forkert)
    
    alert( countries.sort( (a, b) => a.localeCompare(b) ) ); // Andorra,sterreich,Vietnam (korrekt!)

    reverse

    Metoden arr.reverse vender rkkeflgen af elementerne i arr.

    For eksempel:

    let arr = [1, 2, 3, 4, 5];
    arr.reverse();
    
    alert( arr ); // 5,4,3,2,1

    Den returnerer ogs arrayet arr efter omvendelsen.

    split og join

    Her er situationen fra det virkelige liv. Vi skriver en beskedapp, og personen indtaster en kommasepareret liste over modtagere: John, Pete, Mary. Men for os ville et array af navne vre meget mere bekvemt end en enkelt streng. Hvordan fr vi det?

    Metoden str.split(delim) gr prcis det. Den splitter strengen op i et array efter den givne delimiter delim.

    I eksempel nedenfor splitter vi efter et komma efterfulgt af et mellemrum:

    let names = 'Bilbo, Gandalf, Nazgul';
    
    let arr = names.split(', ');
    
    for (let name of arr) {
      alert( `En besked til ${name}.` ); // En besked til Bilbo  (efterfulgt af de andre navne)
    }

    Metoden split har et valgfrit andet numerisk argument en grnse for arrayets lngde. Hvis det er angivet, ignoreres de ekstra elementer. I praksis bruges det dog sjldent:

    let arr = 'Bilbo, Gandalf, Nazgul, Saruman'.split(', ', 2);
    
    alert(arr); // Bilbo, Gandalf
    Opsplitning i bogstaver

    Kaldet til split(s) med en tom s vil opdele strengen i et array af bogstaver:

    let str = "test";
    
    alert( str.split('') ); // t,e,s,t

    Et kald til arr.join(glue) gr det modsatte af split. Det skaber en streng af arr elementer forbundet med glue imellem dem.

    For eksempel:

    let arr = ['Bilbo', 'Gandalf', 'Nazgul'];
    
    let str = arr.join(';'); // limer arrayet sammen til en streng ved hjlp af ;
    
    alert( str ); // Bilbo;Gandalf;Nazgul

    reduce/reduceRight

    Nr vi har brug for at iterere over et array kan vi bruge forEach, for eller for..of.

    Nr vi har brug for at iterere og returnere data for hvert element kan vi bruge map.

    Metoderne arr.reduce og arr.reduceRight hrer ogs til den kategori, men er lidt mere indviklede. De bruges til at beregne en enkelt vrdi baseret p arrayet.

    Syntaksen er:

    let value = arr.reduce(function(accumulator, item, index, array) {
      // ...
    }, [initial]);

    Funktionen anvendes p alle array-elementer n efter n og brer sit resultat videre til det nste kald.

    Argumenterne for funktionen er:

    • accumulator er resultatet af det forrige funktionskald, svarer til initial frste gang (hvis initial er angivet).
    • item er det aktuelle array-element.
    • index er dets position.
    • array er arrayet.

    Efterhnden som funktionen anvendes, bliver resultatet af det forrige funktionskald videregivet til det nste som det frste argument.

    S det frste argument er i bund og grund akkumulatoren, der gemmer det kombinerede resultat af alle tidligere udfrelser. Og til sidst bliver det resultatet af reduce.

    Lyder det kompliceret?

    Den nemmeste mde at forst det p er ved eksempel.

    Her fr vi summen af et array p n linje:

    let arr = [1, 2, 3, 4, 5];
    
    let result = arr.reduce((sum, current) => sum + current, 0);
    
    alert(result); // 15

    Funktionen, der gives til reduce, bruger kun 2 argumenter, det er typisk nok.

    Lad os se detaljerne i, hvad der sker.

    1. Ved frste krsel er sum den initial vrdi (det sidste argument til reduce), som er 0, og current er det frste array-element, som er 1. S funktionens resultat er 1.
    2. Ved anden krsel er sum = 1, vi lgger det andet array-element (2) til det og returnerer.
    3. Ved tredje krsel er sum = 3 og vi lgger endnu et element til det, og s videre

    Beregningen forlber sledes:

    []

    Eller opsat i form af en tabel, hvor hver rkke reprsenterer et funktionskald p det nste array-element:

    sum current result
    det fr frste kald 0 1 1
    det andet kald 1 2 3
    det tredje kald 3 3 6
    det fjerde kald 6 4 10
    det femte kald 10 5 15

    Her kan vi tydeligt se, hvordan resultatet af det forrige kald bliver det frste argument i det nste.

    Vi kan ogs udelade den initiale vrdi, s reduce starter med det frste element i arrayet som det frste argument og starter iterationen fra det andet element:

    let arr = [1, 2, 3, 4, 5];
    
    // fjernet initial vrdi fra reduce (ingen 0 til sidst)
    let result = arr.reduce((sum, current) => sum + current);
    
    alert( result ); // 15

    Resultatet er det samme. Det sker fordi reduce tager det frste element i arrayet som den initiale vrdi og starter iterationen fra det andet element hvis der ikke er angivet en initial vrdi.

    Beregningstabellen er den samme som ovenfor, minus den frste rkke.

    Men sdan brug krver at du er lidt opmrksom. Hvis arrayet er tomt, s giver et kald til reduce uden initial vrdi en fejl.

    Her er et eksempel:

    let arr = [];
    
    // TypeError: Reduce of empty array with no initial value
    // hvis den initiale vrdi eksisterede, ville reduce returnere den for det tomme array.
    arr.reduce((sum, current) => sum + current);

    S det anbefales altid at angive den initiale vrdi.

    Metoden arr.reduceRight gr det samme, men gr fra hjre mod venstre.

    Array.isArray

    Et array er ikke en separat datatype. De er baseret p objekter.

    S typeof hjlper ikke med at skelne den fra et regulrt objekt:

    alert(typeof {}); // object
    alert(typeof []); // object (samme)

    Men arrays bruges s ofte, at der findes en speciel metode til det: Array.isArray(value). Den returnerer true, hvis value er et array, og false ellers.

    alert(Array.isArray({})); // false
    
    alert(Array.isArray([])); // true

    De fleste metoder understtter thisArg

    Nsten alle array-metoder der kalder funktioner som find, filter, map, med en bemrkelsesvrdig undtagelse af sort, accepterer en valgfri ekstra parameter thisArg.

    Den parameter er ikke forklaret i afsnittene ovenfor, fordi den sjldent bruges. Men for fuldstndighedens skyld skal vi dkke den.

    Her er den fulde syntaks for disse metoder:

    arr.find(func, thisArg);
    arr.filter(func, thisArg);
    arr.map(func, thisArg);
    // ...
    // thisArg er det valgfrie sidste argument

    Vrdien af thisArg-parameteren bliver this for func.

    For eksempel, her bruger vi en metode af army-objektet som et filter, og thisArg sender konteksten til det:

    let army = {
      minAge: 18,
      maxAge: 27,
      canJoin(user) {
        return user.age >= this.minAge && user.age < this.maxAge;
      }
    };
    
    let users = [
      {age: 16},
      {age: 20},
      {age: 23},
      {age: 30}
    ];
    
    // find users, for hvem army.canJoin returnerer true
    let soldiers = users.filter(army.canJoin, army);
    
    alert(soldiers.length); // 2
    alert(soldiers[0].age); // 20
    alert(soldiers[1].age); // 23

    Hvis vi, i eksemplet ovenfor, brugte users.filter(army.canJoin), ville army.canJoin blive kaldt som en selvstndig funktion, med this=undefined, hvilket ville fre til en jeblikkelig fejl.

    Et kald til users.filter(army.canJoin, army) kan erstattes med users.filter(user => army.canJoin(user)), som gr det samme. Den sidstnvnte bruges oftere, da den er lidt nemmere at forst for de fleste.

    Opsummering

    Et cheat sheet over array-metoder:

    • For at tilfje/fjerne elementer:

      • push(...items) tilfjer elementer til slutningen,
      • pop() fjerner et element fra slutningen,
      • shift() fjerner et element fra begyndelsen,
      • unshift(...items) tilfjer elementer til begyndelsen.
      • splice(pos, deleteCount, ...items) ved indeks pos sletter deleteCount elementer og indstter items.
      • slice(start, end) opretter et nyt array, kopierer elementer fra indekset start til end (ikke inklusiv) ind i det.
      • concat(...items) opretter et nyt array: kopierer alle elementer fra det nuvrende og tilfjer items til det. Hvis nogen af items er et array, tages dets elementer.
    • For at sge blandt elementer:

      • indexOf/lastIndexOf(item, pos) leder efter item startende fra position pos, og returnerer indekset eller -1 hvis ikke fundet.
      • includes(value) returnerer true hvis arrayet har value, ellers false.
      • find/filter(func) filtrerer elementer gennem funktionen, returnerer frste/alle vrdier der fr den til at returnere true.
      • findIndex er som find, men returnerer indekset i stedet for en vrdi.
    • For at iterere over elementer:

      • forEach(func) kalder func for hvert element, returnerer ikke noget.
    • For at transformere arrayet:

      • map(func) opretter et nyt array fra resultaterne af at kalde func for hvert element.
      • sort(func) sorterer arrayet p stedet, og returnerer det.
      • reverse() vender arrayet om p stedet, og returnerer det.
      • split/join konverterer en streng til et array og tilbage.
      • reduce/reduceRight(func, initial) beregner en enkelt vrdi over arrayet ved at kalde func for hvert element og videregive et mellemliggende resultat mellem kald.
    • Derudover:

      • Array.isArray(value) tjekker om value er et array, hvis ja returnerer true, ellers false.

    Bemrk venligst, at metoderne sort, reverse og splice ndrer arrayet selv.

    Disse metoder er de mest brugte, de dkker 99% af brugstilflde. Men der er f andre:

    • arr.some(fn)/arr.every(fn) tjekker arrayet.

      Funktionen fn kaldes p hvert element i arrayet p samme mde som med map. Hvis nogen/alle resultater er true, returneres true, ellers false.

      Disse metoder opfrer sig lidt som || og && operatorerne: hvis fn returnerer en sand vrdi, returnerer arr.some() straks true og stopper iterationen over de resterende elementer; hvis fn returnerer en falsk vrdi, returnerer arr.every() straks false og stopper iterationen over de resterende elementer.

      Vi kan bruge every til at sammenligne arrays:

      function arraysEqual(arr1, arr2) {
        return arr1.length === arr2.length && arr1.every((value, index) => value === arr2[index]);
      }
      
      alert( arraysEqual([1, 2], [1, 2])); // true
    • arr.fill(value, start, end) fylder arrayet med value fra indeks start til end.

    • arr.copyWithin(target, start, end) kopierer sine elementer fra position start til position end ind i sig selv, ved position target (overskriver eksisterende).

    • arr.flat(depth)/arr.flatMap(fn) opretter et nyt fladt array fra et multidimensionelt array.

    For the komplette fulde liste, se manualen.

    Ved frste jekast kan det virke som om der er s mange metoder, at det er ret svrt at huske dem alle. Men ved at huske de vigtigste er du langt.

    Kig p cheat sheet ovenfor og v dig p dem. Ls derefter opgaverne i dette kapitel for at ve dig, s du fr erfaring med array-metoder.

    Herefter, nr du har brug for at gre noget med et array, og du ikke ved hvordan kom herhen, kig p cheat sheet og find den rigtige metode. Eksempler vil hjlpe dig med at skrive det korrekt. Snart vil du automatisk huske metoderne, uden specifikke anstrengelser fra din side.

    Opgaver

    vigtighed: 5

    Skriv funktionen camelize(str), der ndrer ord adskilt af bindestreger som min-korte-streng til camelCase minKorteStreng.

    Det vil sige: fjern alle bindestreger, og hvert ord efter en bindestreg bliver skrevet med stort begyndelsesbogstav.

    Eksempler:

    camelize("background-color") == 'backgroundColor';
    camelize("list-style-image") == 'listStyleImage';
    camelize("-webkit-transition") == 'WebkitTransition';

    Hint: brug split til at opdele strengen i et array, transformr det og brug join til at stte det sammen igen.

    bn en sandbox med tests.

    lsning
    function camelize(str) {
      return str
        .split('-') // splitter 'mit-lange-ord' til array ['mit', 'lange', 'ord']
        .map(
          // gr frste bogstav stort i alle array-elementer undtagen det frste
          // konverterer ['mit', 'lange', 'ord'] til ['mit', 'Lange', 'Ord']
          (word, index) => index == 0 ? word : word[0].toUpperCase() + word.slice(1)
        )
        .join(''); // samler ['mit', 'Lange', 'Ord'] til 'mitLangeOrd'
    }

    bn lsningen med tests i en sandbox.

    vigtighed: 4

    Skriv en funktion filterRange(arr, a, b) der modtager et array arr, leder efter elementer med vrdier hjere eller lig med a og lavere eller lig med b og returnerer resultatet som et array.

    Funktionen m ikke ndre arrayet. Den skal returnere det nye array.

    For eksempel:

    let arr = [5, 3, 8, 1];
    
    let filtered = filterRange(arr, 1, 4);
    
    alert( filtered ); // 3,1 (matchende vrdier)
    
    alert( arr ); // 5,3,8,1 (ikke ndret)

    bn en sandbox med tests.

    lsning
    function filterRange(arr, a, b) {
      // tilfjer krllede parenteser omkring udtrykket for bedre lsbarhed
      return arr.filter(item => (a <= item && item <= b));
    }
    
    let arr = [5, 3, 8, 1];
    
    let filtered = filterRange(arr, 1, 4);
    
    alert( filtered ); // 3,1 (matchende vrdier)
    
    alert( arr ); // 5,3,8,1 (ikke ndret)

    bn lsningen med tests i en sandbox.

    vigtighed: 4

    Skriv en funktion filterRangeInPlace(arr, a, b) der modtager et array arr og fjerner fra det alle vrdier undtagen dem, der ligger mellem a og b. Testen er: a arr[i] b.

    Funktionen skal kun ndre arrayet. Den m ikke returnere noget.

    For instance:

    let arr = [5, 3, 8, 1];
    
    filterRangeInPlace(arr, 1, 4); // fjernede alle tal undtaget dem fra 1 til 4
    
    alert( arr ); // [3, 1]

    bn en sandbox med tests.

    lsning
    function filterRangeInPlace(arr, a, b) {
    
      for (let i = 0; i < arr.length; i++) {
        let val = arr[i];
    
        // fjern hvis uden for intervallet
        if (val < a || val > b) {
          arr.splice(i, 1);
          i--;
        }
      }
    
    }
    
    let arr = [5, 3, 8, 1];
    
    filterRangeInPlace(arr, 1, 4); // fjernede alle tal undtaget dem fra 1 til 4
    
    alert( arr ); // [3, 1]

    bn lsningen med tests i en sandbox.

    vigtighed: 4
    let arr = [5, 2, 1, -10, 8];
    
    // ... din kode for at sortere i faldende rkkeflge
    
    alert( arr ); // 8, 5, 2, 1, -10
    lsning
    let arr = [5, 2, 1, -10, 8];
    
    arr.sort((a, b) => b - a);
    
    alert( arr );
    vigtighed: 5

    Vi har et array af strenge arr. Vi vil gerne have en sorteret kopi af det, men beholde arr undret.

    Lav en funktion copySorted(arr), der returnerer en sdan kopi.

    let arr = ["HTML", "JavaScript", "CSS"];
    
    let sorted = copySorted(arr);
    
    alert( sorted ); // CSS, HTML, JavaScript
    alert( arr ); // HTML, JavaScript, CSS (ingen ndring)
    lsning

    Vi kan bruge slice() til at lave en kopi og kre sorteringen p den:

    function copySorted(arr) {
      return arr.slice().sort();
    }
    
    let arr = ["HTML", "JavaScript", "CSS"];
    
    let sorted = copySorted(arr);
    
    alert( sorted );
    alert( arr );

    P.S: Der findes en metode der hedder toSorted, som laver en sorteret kopi af et array uden at ndre det originale array. Den er en del af den nye ECMAScript-standard og er tilgngelig i moderne JavaScript-miljer.

    vigtighed: 5

    Opret en konstruktrfunktion Calculator, der skaber udvidelige lommeregner-objekter.

    Opgaven bestr af to dele.

    1. Frst skal du implementere metoden calculate(str), der tager en streng som "1 + 2" i formatet NUMMER operator NUMMER (adskilt af mellemrum) og returnerer resultatet. Den skal forst plus + og minus -.

      Brugseksempel:

      let calc = new Calculator;
      
      alert( calc.calculate("3 + 7") ); // 10
    2. S skal du tilfje metoden addMethod(name, func), der lrer lommeregneren en ny operation. Den tager operatorens name og den to-argument funktion func(a,b), der implementerer den.

      For eksempel, lad os tilfje multiplikation *, division / og potens **:

      let powerCalc = new Calculator;
      powerCalc.addMethod("*", (a, b) => a * b);
      powerCalc.addMethod("/", (a, b) => a / b);
      powerCalc.addMethod("**", (a, b) => a ** b);
      
      let result = powerCalc.calculate("2 ** 3");
      alert( result ); // 8
    • Ingen parenteser eller komplekse udtryk i denne opgave.
    • Tallene og operatoren er adskilt med prcis t mellemrum.
    • Der kan tilfjes fejlhndtering, hvis du nsker det.

    bn en sandbox med tests.

    lsning
    • Vr opmrksom p, hvordan metoderne gemmes. De tilfjes simpelthen til this.methods-egenskaben.
    • Alle tests og numeriske konverteringer udfres i calculate-metoden. I fremtiden kan den udvides til at understtte mere komplekse udtryk.
    function Calculator() {
    
      this.methods = {
        "-": (a, b) => a - b,
        "+": (a, b) => a + b
      };
    
      this.calculate = function (str) {
    
        let split = str.split(' '),
          a = +split[0],
          op = split[1],
          b = +split[2];
    
        if (!this.methods[op] || isNaN(a) || isNaN(b)) {
          return NaN;
        }
    
        return this.methods[op](a, b);
      };
    
      this.addMethod = function (name, func) {
        this.methods[name] = func;
      };
    }

    bn lsningen med tests i en sandbox.

    vigtighed: 5

    Du har et array af user objekter, hvor hvert objekt har en user.name. Skriv koden, der konverterer det til et array af navne.

    For eksempel:

    let john = { name: "John", age: 25 };
    let pete = { name: "Pete", age: 30 };
    let mary = { name: "Mary", age: 28 };
    
    let users = [ john, pete, mary ];
    
    let names = /* ... din kode */;
    
    alert( names ); // John, Pete, Mary
    lsning
    let john = { name: "John", age: 25 };
    let pete = { name: "Pete", age: 30 };
    let mary = { name: "Mary", age: 28 };
    
    let users = [ john, pete, mary ];
    
    let names = users.map(item => item.name);
    
    alert( names ); // John, Pete, Mary
    vigtighed: 5

    Du har et array af user objekter, hvert med name, surname og id.

    Skriv koden, der laver et nyt array fra det, bestende af objekter med id og fullName, hvor fullName genereres ud fra name og surname.

    For eksempel:

    let john = { name: "John", surname: "Smith", id: 1 };
    let pete = { name: "Pete", surname: "Hunt", id: 2 };
    let mary = { name: "Mary", surname: "Key", id: 3 };
    
    let users = [ john, pete, mary ];
    
    let usersMapped = /* ... din kode ... */
    
    /*
    usersMapped = [
      { fullName: "John Smith", id: 1 },
      { fullName: "Pete Hunt", id: 2 },
      { fullName: "Mary Key", id: 3 }
    ]
    */
    
    alert( usersMapped[0].id ) // 1
    alert( usersMapped[0].fullName ) // John Smith
    ``` S, faktisk skal du mappe et array af objekter til et andet. Prv at bruge `=>` her. Der er en lille "catch".
    lsning
    let john = { name: "John", surname: "Smith", id: 1 };
    let pete = { name: "Pete", surname: "Hunt", id: 2 };
    let mary = { name: "Mary", surname: "Key", id: 3 };
    
    let users = [ john, pete, mary ];
    
    let usersMapped = users.map(user => ({
      fullName: `${user.name} ${user.surname}`,
      id: user.id
    }));
    
    /*
    usersMapped = [
      { fullName: "John Smith", id: 1 },
      { fullName: "Pete Hunt", id: 2 },
      { fullName: "Mary Key", id: 3 }
    ]
    */
    
    alert( usersMapped[0].id ); // 1
    alert( usersMapped[0].fullName ); // John Smith

    Vr opmrksom p at med arrow funktionen vi brug for yderligere parenteser.

    :

    let usersMapped = users.map(user => {
      fullName: `${user.name} ${user.surname}`,
      id: user.id
    });

    Som vi husker, er der to typer arrow funktioner: uden krop value => expr og med krop value => {...}.

    I dette tilflde vil JavaScript behandle { som starten p funktionskroppen, ikke starten p objektet. Lsningen er at omslutte dem i almindelige parenteser:

    let usersMapped = users.map(user => ({
      fullName: `${user.name} ${user.surname}`,
      id: user.id
    }));

    Nu virker det fint.

    vigtighed: 5

    Skriv en funktion sortByAge(users), der modtager et array af objekter med egenskaben age og sorterer dem efter age.

    For eksempel:

    let john = { name: "John", age: 25 };
    let pete = { name: "Pete", age: 30 };
    let mary = { name: "Mary", age: 28 };
    
    let arr = [ pete, john, mary ];
    
    sortByAge(arr);
    
    // nu: [john, mary, pete]
    alert(arr[0].name); // John
    alert(arr[1].name); // Mary
    alert(arr[2].name); // Pete
    lsning
    function sortByAge(arr) {
      arr.sort((a, b) => a.age - b.age);
    }
    
    let john = { name: "John", age: 25 };
    let pete = { name: "Pete", age: 30 };
    let mary = { name: "Mary", age: 28 };
    
    let arr = [ pete, john, mary ];
    
    sortByAge(arr);
    
    // nu er de sorteret: [john, mary, pete]
    alert(arr[0].name); // John
    alert(arr[1].name); // Mary
    alert(arr[2].name); // Pete
    vigtighed: 3

    Skriv en funktion shuffle(array) der blander (tilfldigt omarrangerer) elementerne i arrayet.

    Flere kringer af shuffle kan fre til forskellige rkkeflger af elementer. For eksempel:

    let arr = [1, 2, 3];
    
    shuffle(arr);
    // arr = [3, 2, 1]
    
    shuffle(arr);
    // arr = [2, 1, 3]
    
    shuffle(arr);
    // arr = [3, 1, 2]
    // ...

    Alle elementrkkeflger skal have lige stor sandsynlighed. For eksempel kan [1,2,3] omarrangeres som [1,2,3] eller [1,3,2] eller [3,1,2] osv., med lige stor sandsynlighed for hver tilfldighed.

    lsning

    Den simple lsning kunne vre:

    function shuffle(array) {
      array.sort(() => Math.random() - 0.5);
    }
    
    let arr = [1, 2, 3];
    shuffle(arr);
    alert(arr);

    Det virker nogenlunde, fordi Math.random() - 0.5 er et tilfldigt tal, der kan vre positivt eller negativt, s sorteringsfunktionen omarrangerer elementerne tilfldigt.

    Men fordi sorteringsfunktionen ikke er beregnet til at blive brugt p denne mde, har ikke alle permutationer samme sandsynlighed.

    For eksempel, se p koden nedenfor. Den krer shuffle 1000000 gange og tller forekomster af alle mulige resultater:

    function shuffle(array) {
      array.sort(() => Math.random() - 0.5);
    }
    
    // tller forekomster af alle mulige permutationer
    let count = {
      '123': 0,
      '132': 0,
      '213': 0,
      '231': 0,
      '321': 0,
      '312': 0
    };
    
    for (let i = 0; i < 1000000; i++) {
      let array = [1, 2, 3];
      shuffle(array);
      count[array.join('')]++;
    }
    
    // vis tllinger af alle mulige permutationer
    for (let key in count) {
      alert(`${key}: ${count[key]}`);
    }

    Et eksempel resultat (afhnger af JS-motoren):

    123: 250706
    132: 124425
    213: 249618
    231: 124880
    312: 125148
    321: 125223

    Vi kan tydeligt se skvheden: 123 og 213 forekommer meget oftere end andre.

    Resultatet af koden kan variere mellem JavaScript-motorer, men vi kan allerede se, at tilgangen er uplidelig.

    Hvorfor virker det ikke? Generelt set er sort en sort boks: vi smider et array og en sammenligningsfunktion ind i den og forventer, at arrayet bliver sorteret. Men p grund af den totale tilfldighed i sammenligningen gr den sorte boks amok, og hvordan den prcist gr amok afhnger af den konkrete implementering, der varierer mellem motorer.

    Der findes andre gode mder at lse opgaven p. For eksempel er der en fremragende algoritme kaldet Fisher-Yates shuffle. Ideen er at g arrayet igennem i omvendt rkkeflge og bytte hvert element med et tilfldigt et fr det. Det ser sdan ud:

    function shuffle(array) {
      for (let i = array.length - 1; i > 0; i--) {
        let j = Math.floor(Math.random() * (i + 1)); // random index from 0 to i
    
        // bytter elementerne array[i] og array[j]
        // vi bruger "destructuring assignment" syntaks til at opn det
        // du vil finde flere detaljer om den syntaks i senere kapitler
        // det samme kan skrives som:
        // let t = array[i]; array[i] = array[j]; array[j] = t
        [array[i], array[j]] = [array[j], array[i]];
      }
    }

    Lad os teste det p samme mde:

    function shuffle(array) {
      for (let i = array.length - 1; i > 0; i--) {
        let j = Math.floor(Math.random() * (i + 1));
        [array[i], array[j]] = [array[j], array[i]];
      }
    }
    
    // antal forekomster af alle mulige permutationer
    let count = {
      '123': 0,
      '132': 0,
      '213': 0,
      '231': 0,
      '321': 0,
      '312': 0
    };
    
    for (let i = 0; i < 1000000; i++) {
      let array = [1, 2, 3];
      shuffle(array);
      count[array.join('')]++;
    }
    
    // vis tllinger af alle mulige permutationer
    for (let key in count) {
      alert(`${key}: ${count[key]}`);
    }

    The example output:

    123: 166693
    132: 166647
    213: 166628
    231: 167517
    312: 166199
    321: 166316

    Det ser bedre ud: alle permutationer forekommer med samme sandsynlighed.

    Desuden er Fisher-Yates-algoritmen meget bedre med hensyn til ydeevne, da der ikke er nogen sorterings overhead.

    vigtighed: 4

    Skriv funktionen getAverageAge(users), der modtager et array af objekter med egenskaben age og returnerer gennemsnitsalderen.

    Formlen for gennemsnittet er (age1 + age2 + ... + ageN) / N.

    For eksempel:

    let john = { name: "John", age: 25 };
    let pete = { name: "Pete", age: 30 };
    let mary = { name: "Mary", age: 29 };
    
    let arr = [ john, pete, mary ];
    
    alert( getAverageAge(arr) ); // (25 + 30 + 29) / 3 = 28
    lsning
    function getAverageAge(users) {
      return users.reduce((prev, user) => prev + user.age, 0) / users.length;
    }
    
    let john = { name: "John", age: 25 };
    let pete = { name: "Pete", age: 30 };
    let mary = { name: "Mary", age: 29 };
    
    let arr = [ john, pete, mary ];
    
    alert( getAverageAge(arr) ); // 28
    vigtighed: 4

    Lad arr vre et array.

    Opret en funktion unique(arr), der skal returnere et array med unikke elementer fra arr.

    For eksempel:

    function unique(arr) {
      /* din kode */
    }
    
    let strings = ["Hare", "Krishna", "Hare", "Krishna",
      "Krishna", "Krishna", "Hare", "Hare", ":-O"
    ];
    
    alert( unique(strings) ); // Hare, Krishna, :-O

    bn en sandbox med tests.

    lsning

    Lad os gennemg array-elementerne:

    • For hvert element tjekker vi, om det resulterende array allerede indeholder det element.
    • Hvis det er tilfldet, ignorerer vi det, ellers tilfjer vi det til resultatet.
    function unique(arr) {
      let result = [];
    
      for (let str of arr) {
        if (!result.includes(str)) {
          result.push(str);
        }
      }
    
      return result;
    }
    
    let strings = ["Hare", "Krishna", "Hare", "Krishna",
      "Krishna", "Krishna", "Hare", "Hare", ":-O"
    ];
    
    alert( unique(strings) ); // Hare, Krishna, :-O

    Koden virker, men der er et potentielt ydelsesproblem i den.

    Metoden result.includes(str) gennemgr internt arrayet result og sammenligner hvert element med str for at finde et match.

    S hvis der er 100 elementer i result og ingen matcher str, vil den gennemg hele result og lave prcis 100 sammenligninger. Og hvis result er stort, som 10000, vil der vre 10000 sammenligninger.

    Det er ikke et problem i sig selv, fordi JavaScript-motorer er meget hurtige, s det at gennemg et array med 10000 elementer kun tager mikrosekunder.

    Men vi laver sdan en test for hvert element i arr i for-lkken.

    S hvis arr.length er 10000, vil vi have noget i retning af 10000*10000 = 100 millioner sammenligninger. Det er meget.

    S lsningen er kun god til sm arrays.

    Senere i kapitlet Map og Set vil vi se, hvordan man optimerer det.

    NB: I moderne JavaScript kan vi bruge en Set til at gre det samme p en mere effektiv mde.

    bn lsningen med tests i en sandbox.

    vigtighed: 4

    Lad os antage, at vi har modtaget et array af brugere i formen {id:..., name:..., age:... }.

    Opret en funktion groupById(arr), der opretter et objekt ud fra det, med id som ngle, og array-elementerne som vrdier.

    For eksempel:

    let users = [
      {id: 'john', name: "John Smith", age: 20},
      {id: 'ann', name: "Ann Smith", age: 24},
      {id: 'pete', name: "Pete Peterson", age: 31},
    ];
    
    let usersById = groupById(users);
    
    /*
    efter kaldet skal vi have:
    
    usersById = {
      john: {id: 'john', name: "John Smith", age: 20},
      ann: {id: 'ann', name: "Ann Smith", age: 24},
      pete: {id: 'pete', name: "Pete Peterson", age: 31},
    }
    */

    Sdan en funktion er virkelig praktisk, nr man arbejder med serverdata.

    I denne opgave antager vi at id er unik. Der m ikke vre to array-elementer med samme id.

    Brug array-metoden .reduce i lsningen.

    bn en sandbox med tests.

    lsning
    function groupById(array) {
      return array.reduce((obj, value) => {
        obj[value.id] = value;
        return obj;
      }, {})
    }

    bn lsningen med tests i en sandbox.

    Tutorial-oversigt

    Kommentarer

    ls dette fr du kommenterer
    • Hvis du har forslag til forbedringer - s opret venligst et GitHub-issue eller en pull request i stedet for at kommentere.
    • Hvis du ikke forstr noget i artiklen - s uddyb venligst.
    • For at indstte f ord kode, brug <code>-taggen, for flere linjer - omslut dem i <pre>-tag, for mere end 10 linjer - brug en sandbox (plnkr, jsbin, codepen)

    Web Proxy Viewer  |  New URL  |  Original Page