Lodash: Ein unterschätzter Helfer für JavaScript-Entwickler
JavaScript-Entwicklern muss Lodash eigentlich nicht mehr vorgestellt werden. Diese Bibliothek ist jedoch so umfangreich, dass man sich leicht überfordert fühlen kann. Aber das muss nicht so sein!
Lodash, Lodash, Lodash… Wo soll man da überhaupt anfangen? 🤔
Es gab eine Zeit, in der das JavaScript-Ökosystem noch in den Kinderschuhen steckte. Man könnte es mit dem Wilden Westen oder einem Dschungel vergleichen, wo viel los war, aber es kaum Antworten auf die alltäglichen Frustrationen und Produktivitätsprobleme der Entwickler gab.
Dann betrat Lodash die Bühne, und es war, als würde eine Flut alles überschwemmen. Von einfachen, alltäglichen Anforderungen wie dem Sortieren bis hin zu komplexen Datenstrukturtransformationen war Lodash vollgepackt (sogar überladen!) mit Funktionen, die das Leben von JS-Entwicklern in pure Glückseligkeit verwandelten.
Hallo Lodash!
Und wo steht Lodash heute? Nun, es bietet immer noch all die tollen Funktionen, die es anfangs bot, und sogar noch ein paar mehr. Es scheint jedoch einen Teil seiner Bedeutung in der JavaScript-Community verloren zu haben. Warum? Dafür gibt es meiner Meinung nach ein paar Gründe:
- Einige Funktionen in der Lodash-Bibliothek waren (und sind immer noch) langsam, wenn sie auf große Listen angewendet wurden. Während dies 95 % der Projekte nicht beeinträchtigt hätte, gaben einflussreiche Entwickler den verbleibenden 5 % Lodash eine schlechte Presse, und die Wirkung schwappte bis in die Basis hinunter.
- Es gibt einen Trend im JS-Ökosystem (man könnte das Gleiche sogar über die Golang-Leute sagen), wo Überheblichkeit häufiger vorkommt als nötig. Sich auf etwas wie Lodash zu verlassen, wird als dumm angesehen und in Foren wie StackOverflow abgetan, wenn Leute solche Lösungen vorschlagen („Was?! Eine ganze Bibliothek für so etwas verwenden? Ich kann filter() mit Reduce() kombinieren, um dasselbe in einer einfachen Funktion zu erreichen!“).
- Lodash ist alt. Zumindest nach JS-Maßstäben. Es kam 2012 heraus, also sind seit seiner Entstehung fast zehn Jahre vergangen. Die API ist stabil und es können nicht jedes Jahr viele aufregende Dinge hinzugefügt werden (einfach, weil es nicht nötig ist), was für den durchschnittlich überdrehten JS-Entwickler zu Langeweile führt.
Meiner Meinung nach ist die Nichtverwendung von Lodash ein erheblicher Verlust für unsere JavaScript-Codebasen. Es hat sich als fehlerfreie und elegante Lösung für alltägliche Probleme erwiesen, denen wir bei der Arbeit begegnen, und seine Verwendung macht unseren Code lesbarer und wartbarer.
Nachdem das gesagt ist, wollen wir uns einige der gebräuchlichsten (oder auch nicht!) Lodash-Funktionen ansehen und herausfinden, wie unglaublich hilfreich und nützlich diese Bibliothek ist.
Klonen… tief!
Da Objekte in JavaScript per Referenz übergeben werden, bereitet es Entwicklern Kopfzerbrechen, wenn sie etwas klonen wollen, in der Hoffnung, dass der neue Datensatz anders ist.
let personen = [ { name: 'Arnold', specialization: 'C++', }, { name: 'Phil', specialization: 'Python', }, { name: 'Percy', specialization: 'JS', }, ]; // Finde Personen, die C++ schreiben let programmiererCpp = personen.filter((person) => person.specialization == 'C++'); // Wandle sie in JS um! for (person of programmiererCpp) { person.specialization = 'JS'; } console.log(programmiererCpp); // [ { name: 'Arnold', specialization: 'JS' } ] console.log(personen); /* [ { name: 'Arnold', specialization: 'JS' }, { name: 'Phil', specialization: 'Python' }, { name: 'Percy', specialization: 'JS' } ] */
Beachte, wie in unserer reinen Unschuld und trotz unserer guten Absichten die ursprüngliche Personengruppe während des Prozesses mutierte (Arnolds Spezialisierung änderte sich von C++ zu JS) – ein schwerer Schlag für die Integrität des zugrunde liegenden Softwaresystems! Tatsächlich benötigen wir eine Möglichkeit, eine echte (tiefe) Kopie des ursprünglichen Arrays zu erstellen.
Hier kommt Lodash ins Spiel!
Man könnte argumentieren, dass dies eine „dumme“ Art der Codierung in JS ist; die Realität ist jedoch etwas komplizierter. Ja, wir haben den schönen Destrukturierungsoperator zur Verfügung, aber jeder, der versucht hat, komplexe Objekte und Arrays zu destrukturieren, kennt den Schmerz. Dann gibt es die Idee, Serialisierung und Deserialisierung (vielleicht JSON) zu verwenden, um tiefes Kopieren zu erreichen, aber es macht deinen Code nur unordentlicher für den Leser.
Im Gegensatz dazu, sieh, wie erstaunlich elegant und prägnant die Lösung ist, wenn Lodash verwendet wird:
const _ = require('lodash'); let personen = [ { name: 'Arnold', specialization: 'C++', }, { name: 'Phil', specialization: 'Python', }, { name: 'Percy', specialization: 'JS', }, ]; let personenKopie = _.cloneDeep(personen); // Finde Personen, die C++ schreiben let programmiererCpp = personenKopie.filter( (person) => person.specialization == 'C++' ); // Wandle sie in JS um! for (person of programmiererCpp) { person.specialization = 'JS'; } console.log(programmiererCpp); // [ { name: 'Arnold', specialization: 'JS' } ] console.log(personen); /* [ { name: 'Arnold', specialization: 'C++' }, { name: 'Phil', specialization: 'Python' }, { name: 'Percy', specialization: 'JS' } ] */
Beachte, dass das Array personen nach dem Deep Cloning unberührt bleibt (Arnold ist in diesem Fall immer noch auf C++ spezialisiert). Aber was noch wichtiger ist, der Code ist einfach zu verstehen.
Entferne Duplikate aus einem Array
Das Entfernen von Duplikaten aus einem Array klingt nach einem hervorragenden Interview- bzw. Whiteboard-Problem (denke daran, im Zweifelsfall eine Hashmap auf das Problem zu werfen!). Und natürlich kannst du dafür immer eine benutzerdefinierte Funktion schreiben, aber was ist, wenn du auf mehrere verschiedene Szenarien triffst, in denen du deine Arrays einzigartig machen möchtest? Du könntest dafür mehrere andere Funktionen schreiben (und riskieren, auf subtile Fehler zu stoßen), oder du könntest einfach Lodash verwenden!
Unser erstes Beispiel für einzigartige Arrays ist ziemlich trivial, aber es zeigt immer noch die Geschwindigkeit und Zuverlässigkeit, die Lodash auf den Tisch bringt. Stell dir vor, du müsstest das tun, indem du die gesamte benutzerdefinierte Logik selbst schreibst!
const _ = require('lodash'); const benutzerIds = [12, 13, 14, 12, 5, 34, 11, 12]; const eindeutigeBenutzerIds = _.uniq(benutzerIds); console.log(eindeutigeBenutzerIds); // [ 12, 13, 14, 5, 34, 11 ]
Beachte, dass das letzte Array nicht sortiert ist, was hier natürlich nicht von Bedeutung ist. Aber jetzt stellen wir uns ein komplizierteres Szenario vor: Wir haben ein Array von Benutzern, die wir irgendwoher geholt haben, aber wir möchten sicherstellen, dass es nur eindeutige Benutzer enthält. Einfach mit Lodash!
const _ = require('lodash'); const benutzer = [ { id: 10, name: 'Phil', age: 32 }, { id: 8, name: 'Jason', age: 44 }, { id: 11, name: 'Rye', age: 28 }, { id: 10, name: 'Phil', age: 32 }, ]; const eindeutigeBenutzer = _.uniqBy(benutzer, 'id'); console.log(eindeutigeBenutzer); /* [ { id: 10, name: 'Phil', age: 32 }, { id: 8, name: 'Jason', age: 44 }, { id: 11, name: 'Rye', age: 28 } ] */
In diesem Beispiel haben wir die Methode uniqBy() verwendet, um Lodash mitzuteilen, dass wir möchten, dass die Objekte in der Eigenschaft id eindeutig sind. In einer Zeile haben wir ausgedrückt, was 10-20 Zeilen hätte dauern können und mehr Spielraum für Fehler eingeführt!
In Lodash gibt es noch viel mehr Möglichkeiten, Dinge einzigartig zu machen, und ich ermutige dich, einen Blick in die Dokumente zu werfen.
Differenz zweier Arrays
Vereinigung, Differenz usw. mögen nach Begriffen klingen, die am besten in langweiligen Highschool-Vorlesungen über Mengenlehre zurückgelassen werden, aber sie tauchen im täglichen Leben häufiger auf als man denkt. Es ist üblich, eine Liste zu haben und eine andere Liste damit zusammenzuführen oder herauszufinden, welche Elemente für sie im Vergleich zu einer anderen Liste einzigartig sind. Für diese Szenarien ist die Differenzfunktion perfekt.
Beginnen wir die Reise der Unterschiede mit einem einfachen Szenario: Du hast eine Liste aller Benutzer-IDs im System sowie eine Liste der Benutzer erhalten, deren Konten aktiv sind. Wie findest du die inaktiven IDs? Einfach, oder?
const _ = require('lodash'); const alleBenutzerIds = [1, 3, 4, 2, 10, 22, 11, 8]; const aktiveBenutzerIds = [1, 4, 22, 11, 8]; const inaktiveBenutzerIds = _.difference(alleBenutzerIds, aktiveBenutzerIds); console.log(inaktiveBenutzerIds); // [ 3, 2, 10 ]
Und was ist, wenn du, wie es in einer realistischeren Umgebung der Fall ist, mit einer Reihe von Objekten statt mit einfachen Grundelementen arbeiten musst? Nun, Lodash hat dafür eine nette Methode differenceBy()!
const alleBenutzer = [ { id: 1, name: 'Phil' }, { id: 2, name: 'John' }, { id: 3, name: 'Rogg' }, ]; const aktiveBenutzer = [ { id: 1, name: 'Phil' }, { id: 2, name: 'John' }, ]; const inaktiveBenutzer = _.differenceBy(alleBenutzer, aktiveBenutzer, 'id'); console.log(inaktiveBenutzer); // [ { id: 3, name: 'Rogg' } ]
Ordentlich, oder?!
Wie die Differenz gibt es in Lodash andere Methoden für allgemeine Mengenoperationen: Vereinigung, Schnittmenge usw.
Abflachen von Arrays
Die Notwendigkeit, Arrays zu glätten, tritt häufig auf. Ein Anwendungsfall ist, dass du eine API-Antwort erhalten hast und eine map()- und filter()-Kombination auf eine komplexe Liste verschachtelter Objekte/Arrays anwenden musst, um beispielsweise Benutzer-IDs herauszupicken, und jetzt bleiben dir Arrays von Arrays übrig. Hier ist ein Code-Snippet, das diese Situation darstellt:
const bestellDaten = { internal: [ { userId: 1, date: '2021-09-09', amount: 230.0, type: 'prepaid' }, { userId: 2, date: '2021-07-07', amount: 130.0, type: 'prepaid' }, ], external: [ { userId: 3, date: '2021-08-08', amount: 30.0, type: 'postpaid' }, { userId: 4, date: '2021-06-06', amount: 330.0, type: 'postpaid' }, ], }; // finde Benutzer-IDs, die Postpaid-Bestellungen aufgegeben haben (intern oder extern) const postpaidBenutzerIds = []; for (const [bestellTyp, bestellungen] of Object.entries(bestellDaten)) { postpaidBenutzerIds.push(bestellungen.filter((bestellung) => bestellung.type === 'postpaid')); } console.log(postpaidBenutzerIds);
Kannst du erraten, wie postPaidUserIds jetzt aussehen? Hinweis: Es ist widerlich!
[ [], [ { userId: 3, date: '2021-08-08', amount: 30, type: 'postpaid' }, { userId: 4, date: '2021-06-06', amount: 330, type: 'postpaid' } ] ]
Nun, wenn du eine vernünftige Person bist, möchtest du keine benutzerdefinierte Logik schreiben, um die Auftragsobjekte zu extrahieren und sie schön in einer Reihe in einem Array anzuordnen. Verwende einfach die Methode flatten() und genieß die Früchte:
const flacheBenutzerIds = _.flatten(postpaidBenutzerIds); console.log(flacheBenutzerIds); /* [ { userId: 3, date: '2021-08-08', amount: 30, type: 'postpaid' }, { userId: 4, date: '2021-06-06', amount: 330, type: 'postpaid' } ] */
Beachte, dass flatten() nur eine Ebene tief geht. Das heißt, wenn deine Objekte zwei, drei oder mehr Ebenen tief stecken, wird flatten() dich enttäuschen. In diesen Fällen hat Lodash die Methode flattenDeep(), aber sei gewarnt, dass die Anwendung dieser Methode auf sehr große Strukturen die Dinge verlangsamen kann (da hinter den Kulissen eine rekursive Operation am Werk ist).
Ist das Objekt/Array leer?
Dank der Art und Weise, wie „falsche“ Werte und Typen in JavaScript funktionieren, führt manchmal etwas so Einfaches wie das Prüfen auf Leerheit zu existenzieller Angst.
Wie prüfst du, ob ein Array leer ist? Du kannst überprüfen, ob seine Länge 0 ist oder nicht. Wie prüfst du nun, ob ein Objekt leer ist? Nun… Moment mal! Hier setzt dieses ungute Gefühl ein, und diese JavaScript-Beispiele, die Dinge enthalten wie [] == false und {} == false, beginnen unsere Köpfe zu umkreisen. Wenn du unter Druck stehst, ein Feature zu liefern, sind Landminen wie diese das Letzte, was du brauchst – sie machen deinen Code schwer verständlich und führen zu Unsicherheit in deiner Testsuite.
Arbeiten mit fehlenden Daten
In der realen Welt gehorchen uns Daten nicht; egal wie sehr wir es uns wünschen, sie sind selten stromlinienförmig und vernünftig. Ein typisches Beispiel sind fehlende Null-Objekte/Arrays in einer großen Datenstruktur, die als API-Antwort empfangen wird.
Angenommen, wir haben das folgende Objekt als API-Antwort erhalten:
const apiAntwort = { id: 33467, paymentRefernce: 'AEE3356T68', // `order` object missing processedAt: `2021-10-10 00:00:00`, };
Wie gezeigt, erhalten wir im Allgemeinen ein Auftragsobjekt in der Antwort von der API, aber das ist nicht immer der Fall. Was ist also, wenn wir Code haben, der auf diesem Objekt basiert? Eine Möglichkeit wäre, defensiv zu codieren, aber je nachdem, wie verschachtelt das Auftragsobjekt ist, würden wir bald sehr hässlichen Code schreiben, wenn wir Laufzeitfehler vermeiden möchten:
if ( apiAntwort.order && apiAntwort.order.payee && apiAntwort.order.payee.address ) { console.log( 'Die Bestellung wurde an die Postleitzahl gesendet: ' + apiAntwort.order.payee.address.zipCode ); }
🤢🤢 Ja, sehr hässlich zu schreiben, sehr hässlich zu lesen, sehr hässlich zu pflegen und so weiter. Zum Glück hat Lodash eine unkomplizierte Art, mit solchen Situationen umzugehen.
const zipCode = _.get(apiAntwort, 'order.payee.address.zipCode'); console.log('Die Bestellung wurde an die Postleitzahl gesendet: ' + zipCode); // Die Bestellung wurde an die Postleitzahl gesendet: undefined
Es gibt auch die fantastische Option, einen Standardwert anzugeben, anstatt für fehlende Dinge undefiniert zu werden:
const zipCode2 = _.get(apiAntwort, 'order.payee.address.zipCode', 'NA'); console.log('Die Bestellung wurde an die Postleitzahl gesendet: ' + zipCode2); // Die Bestellung wurde an die Postleitzahl gesendet: NA
Ich weiß nicht, wie es dir geht, aber get() ist eines dieser Dinge, die mir Tränen der Freude in die Augen treiben. Es ist nichts Auffälliges. Es gibt keine konsultierte Syntax oder Optionen zum Auswendiglernen, aber sieh dir an, wie viel kollektives Leid es lindern kann! 😇
Entprellung
Falls du nicht vertraut bist, Entprellen ist ein häufiges Thema in der Frontend-Entwicklung. Die Idee ist, dass es manchmal vorteilhaft ist, eine Aktion nicht sofort, sondern nach einiger Zeit (im Allgemeinen einige Millisekunden) zu starten. Was bedeutet das? Hier ist ein Beispiel.
Stell dir eine E-Commerce-Website mit einer Suchleiste vor (jede Website/Web-App heutzutage!). Für eine bessere UX möchten wir nicht, dass der Benutzer die Eingabetaste drücken muss (oder schlimmer noch, die Schaltfläche „Suchen“ drücken muss), um Vorschläge/Vorschauen basierend auf seinem Suchbegriff anzuzeigen. Aber die offensichtliche Antwort ist etwas überladen: Wenn wir onChange() einen Event-Listener für die Suchleiste hinzufügen und für jeden Tastendruck einen API-Aufruf auslösen, hätten wir einen Alptraum für unser Backend geschaffen. Es würde zu viele unnötige Aufrufe geben (wenn zum Beispiel nach „Weiße Teppichbürste“ gesucht wird, gibt es insgesamt 18 Anfragen!) und fast alle davon sind irrelevant, weil die Benutzereingabe noch nicht abgeschlossen ist.
Die Antwort liegt im Entprellen, und die Idee ist folgende: Sende keinen API-Aufruf, sobald sich der Text ändert. Warte einige Zeit (z. B. 200 Millisekunden), und wenn zu diesem Zeitpunkt ein weiterer Tastendruck erfolgt, breche die frühere Zeitzählung ab und beginne erneut mit dem Warten. Daher senden wir nur dann eine API-Anfrage an das Backend, wenn der Benutzer eine Pause einlegt (entweder, weil er nachdenkt oder weil er fertig ist und eine Antwort erwartet).
Die von mir beschriebene Gesamtstrategie ist kompliziert, und ich werde nicht auf die Synchronisierung von Timer-Management und -Abbruch eingehen; der eigentliche Entprellprozess ist jedoch sehr einfach, wenn du Lodash verwendest.
const _ = require('lodash'); const axios = require('axios'); // Das ist übrigens eine echte Hunde-API! const fetchHundeRassen = () => axios .get('https://dog.ceo/api/breeds/list/all') .then((res) => console.log(res.data)); const debouncedFetchHundeRassen = _.debounce(fetchHundeRassen, 1000); // nach einer Sekunde debouncedFetchHundeRassen(); // zeigt Daten nach einiger Zeit
Wenn du an setTimeout() denkst, das den gleichen Job erledigt, dann gibt es noch mehr! Die Entprellung von Lodash verfügt über viele leistungsstarke Funktionen; beispielsweise möchtest du möglicherweise sicherstellen, dass die Entprellung nicht unbegrenzt ist. Das heißt, selbst wenn jedes Mal, wenn die Funktion ausgelöst werden soll, ein Tastendruck erfolgt (wodurch der Gesamtprozess abgebrochen wird), solltest du sicherstellen, dass der API-Aufruf trotzdem nach beispielsweise zwei Sekunden erfolgt. Dafür hat Lodash debounce() die Option maxWait:
const debouncedFetchHundeRassen = _.debounce(fetchHundeRassen, 150, { maxWait: 2000 }); // debounce für 250ms, aber sende die API-Anfrage trotzdem nach 2 Sekunden
Schau dir die offiziellen Dokumente für ein tieferes Eintauchen an. Sie sind voll mit superwichtigen Sachen!
Werte aus einem Array entfernen
Ich weiß nicht, wie es dir geht, aber ich hasse es, Code zum Entfernen von Elementen aus einem Array zu schreiben. Zuerst muss ich den Index des Elements abrufen, überprüfen, ob der Index tatsächlich gültig ist, und wenn ja, die Methode splice() aufrufen, und so weiter. Ich kann mich nie an die Syntax erinnern und muss daher ständig nachschlagen, und am Ende bleibt das nagende Gefühl, dass ich mir einen dummen Fehler eingeschlichen habe.
const grüße = ['hallo', 'hi', 'hey', 'winken', 'hi']; _.pull(grüße, 'winken', 'hi'); console.log(grüße); // [ 'hallo', 'hey' ]
Bitte beachte zwei Dinge:
- Das ursprüngliche Array wurde dabei geändert.
- Die Methode pull() entfernt alle Instanzen, auch wenn es Duplikate gibt.
Es gibt eine andere verwandte Methode namens pullAll(), die ein Array als zweiten Parameter akzeptiert, was es einfacher macht, mehrere Elemente gleichzeitig zu entfernen. Zugegeben, wir könnten pull() einfach mit einem Spread-Operator verwenden, aber denke daran, dass Lodash zu einer Zeit kam, als der Spread-Operator noch nicht einmal ein Vorschlag in der Sprache war!
const grüße2 = ['hallo', 'hi', 'hey', 'winken', 'hi']; _.pullAll(grüße2, ['winken', 'hi']); console.log(grüße2); // [ 'hallo', 'hey' ]
Letzter Index eines Elements
Die native indexOf()-Methode von JavsScript ist cool, außer wenn du daran interessiert bist, das Array aus der entgegengesetzten Richtung zu scannen! Und noch einmal, ja, du könntest einfach eine dekrementierende Schleife schreiben und das Element finden, aber warum nicht eine viel elegantere Technik verwenden?
Hier ist eine schnelle Lodash-Lösung mit der Methode lastIndexOf():
const ganzeZahlen = [2, 4, 1, 6, -1, 10, 3, -1, 7]; const index = _.lastIndexOf(ganzeZahlen, -1); console.log(index); // 7
Leider gibt es keine Variante dieser Methode, mit der wir komplexe Objekte nachschlagen oder sogar eine benutzerdefinierte Suchfunktion übergeben können.
Reißverschluss. Entpacken!
Wenn du nicht in Python gearbeitet hast, ist zip/unzip ein Dienstprogramm, das du in deiner gesamten Karriere als JavaScript-Entwickler vielleicht nie bemerken oder dir vorstellen kannst. Und das vielleicht aus gutem Grund: Zip/Unzip ist selten so dringend erforderlich wie filter() usw. Es ist jedoch eines der besten, weniger bekannten Dienstprogramme, das es gibt, und kann dir in einigen Situationen dabei helfen, prägnanten Code zu erstellen.
Im Gegensatz zu dem, was sich anhört, hat zip/unzip nichts mit Komprimierung zu tun. Stattdessen handelt es sich um eine Gruppierungsoperation, bei der Arrays derselben Länge in ein einzelnes Array von Arrays konvertiert werden können, wobei Elemente an derselben Position zusammengepackt (zip()) und wieder zurück (unzip()) werden. Ja, ich weiß, es wird verschwommen, wenn man versucht, mit Worten auszukommen, also schauen wir uns etwas Code an:
const tiere = ['Ente', 'Schaf']; const größen = ['klein', 'groß']; const gewicht = ['weniger', 'mehr']; const gruppierteTiere = _.zip(tiere, größen, gewicht); console.log(gruppierteTiere); // [ [ 'Ente', 'klein', 'weniger' ], [ 'Schaf', 'groß', 'mehr' ] ]
Die ursprünglichen drei Arrays wurden in ein einziges mit nur zwei Arrays umgewandelt. Und jedes dieser neuen Arrays repräsentiert ein einzelnes Tier mit all seinen Inhalten an einem Ort. Der Index 0 sagt uns also, um welche Tierart es sich handelt, der Index 1 sagt uns seine Größe und der Index 2 sagt uns sein Gewicht. Dadurch ist es jetzt einfacher, mit den Daten zu arbeiten. Sobald du alle erforderlichen Operationen auf die Daten angewendet hast, kannst du sie mit unzip() wieder auflösen und an die ursprüngliche Quelle zurücksenden:
const tierDaten = _.unzip(gruppierteTiere); console.log(tierDaten); // [ [ 'Ente', 'Schaf' ], [ 'klein', 'groß' ], [ 'weniger', 'mehr' ] ]
Das Zip/Unzip-Dienstprogramm wird dein Leben nicht über Nacht verändern, aber eines Tages wird es dein Leben verändern!
Fazit 👨🏫
(Ich habe den gesamten Quellcode, der in diesem Artikel verwendet wird, hier, damit du ihn direkt im Browser ausprobieren kannst!)
Die Lodash Dokumente sind voll von Beispielen und Funktionen, die dich umhauen werden. In einer Zeit, in der der Masochismus im JS-Ökosystem zuzunehmen scheint, ist Lodash wie ein Hauch frischer Luft, und ich empfehle dir dringend, diese Bibliothek in deinen Projekten zu verwenden!