So verwenden Sie die .map()-Methode in JavaScript, um ein Array von Objekten dynamisch zu ändern.
Erste Schritte
Da der Code, den wir für dieses Tutorial schreiben, „eigenständig“ ist (d. h. nicht Teil einer größeren App oder eines größeren Projekts ist), erstellen wir ein Node.js-Projekt von Grund auf neu. Wenn Sie Node.js noch nicht auf Ihrem Computer installiert haben, lesen Sie zuerst dieses Tutorial und kehren Sie dann hierher zurück.
Sobald Sie Node.js auf Ihrem Computer installiert haben, können Sie aus Ihrem Projektordner auf Ihrem Computer (z. B. ~/projects
), erstellen Sie einen neuen Ordner für unsere Arbeit:
Terminal
mkdir map
Als nächstes cd
in dieses Verzeichnis und erstellen Sie eine index.js
Datei (hier schreiben wir unseren Code für das Tutorial):
Terminal
cd map && touch index.js
Führen Sie als Nächstes im selben Ordner npm init -f
aus um einen package.json
zu bootstrappen Datei:
Terminal
npm init -f
Dadurch wird NPM (Node Package Manager) angewiesen, einen neuen package.json
zu erstellen Datei in Ihrer App. Die -f
part steht für "force" und überspringt den Schritt-für-Schritt-Assistenten, den Sie sehen, wenn Sie npm init
ausführen von selbst (Sie können dies gerne verwenden, um zu verstehen, wie es funktioniert).
Schließlich müssen wir noch zwei Abhängigkeiten installieren:dayjs
und currency.js
.
Terminal
npm i dayjs currency.js
Wir verwenden diese beiden, um unsere Daten im Rahmen unseres .map()
zu analysieren und zu formatieren .
Damit können wir loslegen.
Benutzerdaten hinzufügen
Unser Ziel für dieses Tutorial ist die Verwendung von Array.map()
-Methode in JavaScript, um einige Benutzerdaten zu formatieren und uns dabei zu helfen, zu verstehen, wer unsere wertvollsten Benutzer sind. Lassen Sie uns zunächst einige Testdaten in einer separaten Datei im Stammverzeichnis unseres Projekts hinzufügen:
/users.js
export default [
{
"createdAt": "2021-12-08T16:20:14+00:00",
"invoices": [
{
"createdAt": "2021-12-08T16:20:14+00:00",
"amount": 790.31
},
{
"createdAt": "2021-12-07T16:20:14+00:00",
"amount": 893.38
},
{
"createdAt": "2021-12-06T16:20:14+00:00",
"amount": 302.97
},
...
],
"name": {
"first": "Wester",
"last": "Christian"
},
"emailAddress": "[email protected]"
},
...
];
Hinweis:Dies ist eine verkürzte Liste, da die echte Liste (hier auf Github verfügbar) ziemlich lang ist.
Sobald Sie das in der App haben, können wir mit dem Schreiben unseres .map()
fortfahren Funktion über dieses Array.
Zuordnung über das Benutzer-Array
Lassen Sie uns zunächst ein Skelett für unseren .map()
erstellen funktionieren und überprüfen und besprechen, wie es funktionieren wird:
/index.js
import users from './users.js';
const spendByUser = users.map((user) => {
// We'll return our modified user here...
});
console.log(spendByUser);
Zurück in unserem /index.js
Datei, hier importieren wir unseren /users.js
Datei als users
(Denken Sie daran, wir haben einen export default
in dieser Datei, sodass wir einfach import users
sagen können in unserem Code – wenn dies ein benannter Export wäre, würden wir so etwas wie import { users } from '...'
sehen ).
Weil wir wissen, dass users
Variable sollte ein Array enthalten (was wir aus /users.js
exportiert haben ), können wir .map()
aufrufen direkt darauf. Das liegt daran, dass .map()
ist eine eingebaute Funktion in JavaScript. Es ist auf Array
definiert Prototyp (der Name, der für das Objekt verwendet wird, das die von einer Funktion in JavaScript geerbte Funktionalität enthält). Wir sagen "A" groß Array
hier, weil das die Funktion in JavaScript ist, die das Verhalten eines Arrays definiert. Als Teil seines Prototypobjekts haben wir den .map()
Funktion (als Methode bekannt, weil es sich um eine Funktion handelt, die für ein vorhandenes Objekt definiert ist).
Wie seine Geschwister .map()
ermöglicht es uns, eine Schleife über ein Array auszuführen und etwas zu tun . Das etwas In diesem Fall werden Elemente in einem Array geändert und zurückgegeben, wodurch ein neues Array mit den geänderten Elementen erstellt wird. Ein kurzes Beispiel:
const greetings = ['Hello', 'Goodbye', 'See ya'];
const greetingsWithName = greetings.map((greeting) => {
return `${greeting}, Ryan!`
});
console.log(greetingsWithName);
// ['Hello, Ryan!', 'Goodbye, Ryan!', 'See ya, Ryan!']
Hier nehmen wir ein Array von Strings und verwenden .map()
um dieses Array zu durchlaufen. Für jeden String im Array geben wir einen neuen String zurück (erstellt mit Backticks, damit wir die String-Interpolation von JavaScript nutzen können). Als Gegenleistung zu unserem Aufruf an greetings.map()
Wir bekommen ein neues Array. Es ist wichtig zu verstehen :Dies ist ein brandneues, einzigartiges Array. Der .map()
Funktion erstellt eine Kopie eines Arrays, das wir .map()
nennen Funktion ein und gibt dieses neue Array zurück.
Hier speichern wir das in einer Variablen greetingsWithName
und dann console.log()
heraus, um die geänderte Kopie zu sehen.
/index.js
import dayjs from 'dayjs';
import users from './users.js';
const spendByUser = users.map((user) => {
return {
isLegacyCustomer: dayjs(user?.createdAt).isAfter(dayjs().subtract(60, 'days')),
name: `${user?.name?.first} ${user?.name?.last}`,
};
});
console.log(spendByUser);
Jetzt verstehen wir die Grundlagen von .map()
, beginnen wir mit der Änderung unseres users
Reihe. Genau dieselben Prinzipien sind im Spiel, wie wir oben gesehen haben:Wir nehmen ein Array, rufen .map()
auf darauf und erhalten im Gegenzug ein neues Array.
Oben, beachten Sie das über unserem users
import haben wir eine der zuvor installierten Abhängigkeiten importiert:dayjs
. Unten in unserem .map()
Funktion übergeben wir im Callback an .map()
, geben wir ein Objekt zurück. Unser Ziel hier ist es, einige "Analysen" für jeden Benutzer durchzuführen und herauszufinden, wie viel jeder Kunde ausgegeben hat und ob es sich um einen Altkunden handelt oder nicht.
Hinweis:Wir müssen nicht genau dieselbe Objektform (oder sogar ein Objekt) von unserem .map()
zurückgeben . Wir müssen nur zurückgeben, was immer wir von dem aktuellen Element ersetzen möchten, das wir im Array abbilden.
Hier wollen wir ein neues Objekt erstellen, das drei Eigenschaften hat:
isLegacyCustomer
was uns als booleschertrue
sagt oderfalse
ob der Kunde als Vermächtnis betrachtet wird oder nicht.name
Dies ist die vollständige Namenszeichenfolge des Benutzers/Kunden.spend
das ist der Geldbetrag, den sie bei uns ausgegeben haben, bestehend aus insgesamt ihreninvoices
Array.
Hier konzentrieren wir uns nur auf isLegacyCustomer
und name
(spend
ist etwas komplizierter, also fügen wir das als nächstes hinzu).
Für isLegacyCustomer
, möchten wir wissen, ob der Benutzer vor mehr als 60 Tagen in unserer Datenbank erstellt wurde (wir tun hier nur so). Um das herauszufinden, nehmen wir den createdAt
Eigenschaft auf user
Objekt und übergeben Sie es an dayjs()
(Die Funktion, die wir aus dem gleichnamigen Paket oben importiert haben).
dayjs
ist eine Bibliothek zum Manipulieren und Arbeiten mit Datumsangaben. Hier verwenden wir zur Erleichterung unserer Arbeit dayjs()
um uns mitzuteilen, ob der Zeitstempel, den wir überschritten haben (user.createdAt
) ist nach ein weiteres Datum, das wir spontan mit einem weiteren Aufruf von dayjs
erstellen :dayjs().subtract(60, 'days')
. Hier bekommen wir einen dayjs
zurück Objekt, das ein Datum vor 60 Tagen enthält.
Als Antwort erwarten wir den .isAfter()
Funktion in dayjs
um uns einen booleschen true
zurückzugeben oder false
.
Für name
Feld erstellen wir eine Zeichenfolge mit dem gleichen Backtick-Muster, das wir zuvor gesehen haben, diesmal mit Interpolation, um den Vor- und Nachnamen unseres Benutzers zu verketten (miteinander zu verbinden) (unter Verwendung des name.first
und name.last
Eigenschaften aus dem name
Objekt auf den Benutzer).
/index.js
import dayjs from 'dayjs';
import currency from 'currency.js';
import users from './users.js';
const spendByUser = users.map((user) => {
return {
isLegacyCustomer: dayjs(user?.createdAt).isAfter(dayjs().subtract(60, 'days')),
name: `${user?.name?.first} ${user?.name?.last}`,
spend: user?.invoices?.reduce((total, invoice) => {
total += invoice.amount;
return currency(total, { precision: 2 }).value;
}, 0),
};
});
console.log(spendByUser);
Jetzt für den kniffligen Teil. Um den spend
zu erhalten Eigenschaft für unsere Benutzer, müssen wir eine andere Array-Methode .reduce()
verwenden um die user.invoices
zu durchlaufen Reihe. Ähnlich einem .map()
, die .reduce()
Methode durchläuft oder iteriert das Array, für das die Methode aufgerufen wird.
Anstelle eines neuen Arrays wird jedoch ein .reduce()
zurückgegeben -Methode gibt den Wert zurück, den wir acc
zuweisen oder "Akkumulator". Der Akkumulator in einer Reduce-Funktion ist ein Wert, der mit einem Wert beginnt und – wenn wir .reduce()
verwenden für den beabsichtigten Zweck – gibt eine modifizierte oder „aktualisierte“ Version dieses Werts zurück.
Hier beginnt der Akkumulator als 0
als zweites Argument an user?.invoices?.reduce()
übergeben (Die Fragezeichen dort sagen nur "Wenn ein Benutzer existiert und Rechnungen darüber existieren, rufen Sie .reduce()
an auf user.invoices
"). Für jede Schleife oder Iteration von user.invoices
, der aktuelle Wert des Akkumulators (wieder beginnend mit diesem 0
) wird als erstes Argument an die Funktion übergeben, die wir an .reduce()
übergeben , hier als total
bezeichnet . Als zweites Argument erhalten wir Zugriff auf das aktuelle Element im Array, das durchlaufen wird.
Wenn wir uns hier unseren Code ansehen, ist unser Ziel, die invoice.amount
zu "summieren". Feld für jedes Objekt im user.invoices
Array.
Für jede Iteration unseres .reduce()
, nehmen wir den aktuellen Wert von total
und fügen Sie den aktuellen invoice.amount
hinzu dazu. Als nächstes nehmen wir das resultierende total
und an currency()
übergeben Funktion, die wir aus currency.js
importiert haben ganz oben in unserer Datei. Dies hilft uns, den Währungswert richtig als Gleitkommazahl zu formatieren (z. B. 123.45
). An diese Funktion übergeben wir total
als erstes Argument und dann ein Optionsobjekt für die Funktion mit precision: 2
als Eigenschaft mit der Aufschrift "Diese Zahl auf zwei Dezimalstellen formatieren."
Abschließend geben wir den .value
zurück -Eigenschaft für das Objekt, das durch den Aufruf von currency(total, { precision: 2 })
zurückgegeben wird . Was wir return
hier wird der neue oder "aktualisierte" Wert für den Akkumulator, der als total
verfügbar sein wird bei der nächsten Schleife/Iteration von user?.invoices
. Damit ist es klar, total
In unserem Code erhalten Sie hier für jede Iteration mit diesem Beispiel-Array Folgendes (vorausgesetzt, wir beginnen bei 0
):
[{ amount: 1 }, { amount: 2.55 }, { amount: 3.50 }]
total = 0 // first item
total = 1
total = 3.55
total = 7.05 // last item
Einmal unsere .reduce()
abgeschlossen ist, erwarten wir den endgültigen Wert von total
(nachdem das letzte Element hinzugefügt wurde) im Gegenzug. Das bedeutet, dass spend
sollte insgesamt spend
enthalten für jeden unserer Benutzer.
Das ist es! Wenn wir das ausprobieren (stellen Sie sicher, dass Sie sich abmelden spendByUser
am Ende unserer Datei), sollten wir etwa Folgendes erhalten:
[
{ isLegacyCustomer: true, name: 'Wester Christian', spend: 10729.91 },
{ isLegacyCustomer: true, name: 'Carthon Weaver', spend: 14926.53 },
{ isLegacyCustomer: true, name: 'Keldrin Durham', spend: 13491.61 },
{ isLegacyCustomer: true, name: 'Jurgen Espinosa', spend: 13179.59 },
...
]
Sehen wir uns zum Schluss an, wie Sie diese Daten nutzen können.
Sortierung basierend auf zugeordneten Daten
Warum sollten wir so etwas tun wollen? Wie die meisten Dinge hängt es von unserem Code und dem Projekt ab, an dem wir arbeiten. Um den Kontext hinzuzufügen, könnten wir jedoch davon ausgehen, dass wir versuchen, einen Kunden zu finden, den wir basierend auf seinen Gesamtausgaben bei unserem Unternehmen belohnen. Jetzt, wo wir unser gemapptes Array zur Hand haben, können wir so etwas tun:
/index.js
import dayjs from 'dayjs';
import currency from 'currency.js';
import users from './users.js';
const spendByUser = users.map((user) => { ... });
const mostValuableCustomer = spendByUser.sort((a, b) => a.spend - b.spend).pop();
console.log({ mostValuableCustomer });
Hier haben wir zwei Zeilen hinzugefügt. Wir haben eine Variable mostValueCustomer
erstellt und darauf setzen wir das Ergebnis des Aufrufs von .sort()
Methode (ein weiterer Array
Prototyp-Methode) und ihr eine Funktion übergeben. Diese Funktion nimmt das aktuelle Element und das nächste Element im Array und vergleicht sie, um herauszufinden, welches zuerst kommen sollte. Hier sortieren wir nach den Gesamtausgaben, um zu sagen:"Beginnen Sie mit den geringsten Ausgaben oben und enden Sie mit den höchsten Ausgaben unten."
Mit diesem Ergebnis (wir erwarten, die sortierte Kopie unserer spendByUser
zurück zu bekommen array), nennen wir .pop()
Methode, um zu sagen:"Legen Sie das letzte Element im Array ab und geben Sie es zurück." Hier der letzte Artikel (der Kunde mit dem höchsten spend
) wird im mostValuableCustomer
gespeichert Variable. Wenn wir diese Variable ausloggen, sollten wir Folgendes erhalten, wenn wir unseren Code ausführen:
{ mostValuableCustomer: { isLegacyCustomer: false, name: 'Vicente Henry', spend: 15755.03 } }
Abschluss
In diesem Tutorial haben wir gelernt, wie man Array.map
verwendet -Methode, um ein vorhandenes Array zu durchlaufen und seinen Inhalt zu ändern. Wir haben auch gelernt, wie man Daten als Teil dieses .map()
formatiert sowie wie die resultierenden Daten in unserem Code verwendet werden.