10 wichtige Lodash-Funktionen für JavaScript-Entwickler
Veröffentlicht: 2021-10-05Für JavaScript-Entwickler braucht Lodash keine Einführung. Die Bibliothek ist jedoch riesig und fühlt sich oft überwältigend an. Nicht länger!
Lodash, Lodash, Lodash. . . wo fange ich überhaupt an!
Es gab eine Zeit, in der das JavaScript-Ökosystem im Entstehen war; es könnte mit dem wilden Westen oder einem Dschungel verglichen werden, wenn man so will, wo viel los war, aber es gab nur sehr wenige Antworten auf die alltäglichen Entwicklerfrustrationen und die Produktivität.
Dann betrat Lodash die Szene und es fühlte sich an wie eine Flut, die alles überflutet. Von einfachen alltäglichen Anforderungen wie Sortieren bis hin zu komplexen Datenstrukturtransformationen war Lodash mit Funktionen vollgestopft (sogar überladen!), die das Leben von JS-Entwicklern in pures Glück verwandelten.

Und wo ist Lodash heute? Nun, es hat immer noch all die Leckereien, die es anfangs bot, und dann einige, aber es scheint in der JavaScript-Community den Verstand verloren zu haben. Wieso den? Ich kann mir einige Gründe vorstellen:
- Einige Funktionen in der Lodash-Bibliothek waren (und sind immer noch) langsam, wenn sie auf große Listen angewendet wurden. Während dies nie 95 % der Projekte da draußen beeinflusst hätte, bescherten einflussreiche Entwickler der verbleibenden 5 % Lodash eine schlechte Presse und der Effekt ging bis in die Basis über.
- Es gibt einen Trend im JS-Ökosystem (vielleicht sogar dasselbe über die Golang-Leute), bei dem Hybris häufiger als nötig ist. Sich auf so etwas wie Lodash zu verlassen, wird als dumm angesehen und wird in Foren wie StackOverflow abgeschossen, wenn Leute solche Lösungen vorschlagen ("Was?! Verwenden Sie eine ganze Bibliothek für so etwas? Ich kann
filter()mitreduce()kombinierenfilter()reduce()zu erreichen dasselbe in einer einfachen Funktion!”). - Lodash ist alt. Zumindest nach JS-Standards. Es kam 2012 heraus, also ist es zum Zeitpunkt des Schreibens fast zehn Jahre her. Die API war 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 durchschnittlichen übererregten JS-Entwickler Langeweile erzeugt.
Meiner Meinung nach ist der Verzicht auf Lodash ein erheblicher Verlust für unsere JavaScript-Codebasen. Es hat sich als fehlerfreie und elegante Lösungen für alltägliche Probleme erwiesen, auf die wir bei der Arbeit stoßen, und seine Verwendung wird unseren Code nur lesbarer und wartungsfreundlicher machen.
Lassen Sie uns nun in einige der üblichen (oder nicht!) Lodash-Funktionen eintauchen und sehen, wie unglaublich hilfreich und schön diese Bibliothek ist.
Klonen. . . tief!
Da Objekte in JavaScript als Referenz übergeben werden, bereitet es Entwicklern Kopfschmerzen, wenn sie etwas klonen möchten, in der Hoffnung, dass der neue Datensatz anders ist.
let people = [ { name: 'Arnold', specialization: 'C++', }, { name: 'Phil', specialization: 'Python', }, { name: 'Percy', specialization: 'JS', }, ]; // Find people writing in C++ let folksDoingCpp = people.filter((person) => person.specialization == 'C++'); // Convert them to JS! for (person of folksDoingCpp) { person.specialization = 'JS'; } console.log(folksDoingCpp); // [ { name: 'Arnold', specialization: 'JS' } ] console.log(people); /* [ { name: 'Arnold', specialization: 'JS' }, { name: 'Phil', specialization: 'Python' }, { name: 'Percy', specialization: 'JS' } ] */ Beachten Sie, wie in unserer reinen Unschuld und trotz unserer guten Absichten das ursprüngliche people Array dabei mutierte (Arnolds Spezialisierung wurde von C++ auf JS geändert) – ein schwerer Schlag für die Integrität des zugrunde liegenden Softwaresystems! Tatsächlich brauchen wir eine Möglichkeit, eine echte (tiefe) Kopie des ursprünglichen Arrays zu erstellen.

Sie können vielleicht argumentieren, dass dies eine „alberne“ Art der Codierung in JS ist; Die Realität ist jedoch etwas kompliziert. 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 (möglicherweise JSON) zu verwenden, um ein tiefes Kopieren zu erreichen, aber es macht Ihren Code für den Leser nur unübersichtlicher.
Schauen Sie sich im Gegensatz dazu an, wie erstaunlich elegant und prägnant die Lösung ist, wenn Lodash verwendet wird:
const _ = require('lodash'); let people = [ { name: 'Arnold', specialization: 'C++', }, { name: 'Phil', specialization: 'Python', }, { name: 'Percy', specialization: 'JS', }, ]; let peopleCopy = _.cloneDeep(people); // Find people writing in C++ let folksDoingCpp = peopleCopy.filter( (person) => person.specialization == 'C++' ); // Convert them to JS! for (person of folksDoingCpp) { person.specialization = 'JS'; } console.log(folksDoingCpp); // [ { name: 'Arnold', specialization: 'JS' } ] console.log(people); /* [ { name: 'Arnold', specialization: 'C++' }, { name: 'Phil', specialization: 'Python' }, { name: 'Percy', specialization: 'JS' } ] */ Beachten Sie, wie das people Array nach dem Deep Cloning unberührt bleibt (Arnold ist in diesem Fall immer noch auf C++ spezialisiert). Aber noch wichtiger ist, dass der Code einfach zu verstehen ist.
Duplikate aus einem Array entfernen
Das Entfernen von Duplikaten aus einem Array klingt nach einem ausgezeichneten Interview-/Whiteboarding-Problem (denken Sie daran, im Zweifelsfall eine Hashmap auf das Problem zu werfen!). Und natürlich können Sie dafür jederzeit eine benutzerdefinierte Funktion schreiben, aber was ist, wenn Sie auf mehrere verschiedene Szenarien stoßen, in denen Sie Ihre Arrays einzigartig machen? Sie könnten dafür mehrere andere Funktionen schreiben (und riskieren, auf subtile Fehler zu stoßen), oder Sie könnten einfach Lodash verwenden!

Unser erstes Beispiel für einzigartige Arrays ist ziemlich trivial, aber es repräsentiert immer noch die Geschwindigkeit und Zuverlässigkeit, die Lodash auf den Tisch bringt. Stellen Sie sich vor, Sie schreiben die gesamte benutzerdefinierte Logik selbst!
const _ = require('lodash'); const userIds = [12, 13, 14, 12, 5, 34, 11, 12]; const uniqueUserIds = _.uniq(userIds); console.log(uniqueUserIds); // [ 12, 13, 14, 5, 34, 11 ]Beachten Sie, dass das letzte Array nicht sortiert ist, was hier natürlich keine Rolle spielt. Stellen wir uns nun ein komplizierteres Szenario vor: Wir haben eine Reihe von Benutzern, die wir von irgendwoher gezogen haben, aber wir möchten sicherstellen, dass sie nur eindeutige Benutzer enthält. Ganz einfach mit Lodash!
const _ = require('lodash'); const users = [ { 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 uniqueUsers = _.uniqBy(users, 'id'); console.log(uniqueUsers); /* [ { 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 die Objekte in der id Eigenschaft eindeutig sein sollen. In einer Zeile haben wir ausgedrückt, was 10-20 Zeilen hätte nehmen können und mehr Spielraum für Fehler eingeführt!
Es gibt noch viel mehr Möglichkeiten, Dinge in Lodash einzigartig zu machen, und ich ermutige Sie, einen Blick in die Dokumentation zu werfen.
Unterschied zweier Arrays
Vereinigung, Differenz usw. mögen nach Begriffen klingen, die am besten in langweiligen High-School-Vorlesungen über Mengenlehre hinterlassen werden, aber sie tauchen in der täglichen Praxis häufiger auf als nicht. Es ist üblich, eine Liste zu haben und eine andere Liste damit zusammenzuführen oder herauszufinden, welche Elemente im Vergleich zu einer anderen Liste einzigartig sind; für diese Szenarien ist die Differenzfunktion perfekt.

Beginnen wir die Reise des Unterschieds mit einem einfachen Szenario: Sie haben eine Liste aller Benutzer-IDs im System sowie eine Liste der Benutzer erhalten, deren Konten aktiv sind. Wie finden Sie die inaktiven IDs? Einfach, oder?
const _ = require('lodash'); const allUserIds = [1, 3, 4, 2, 10, 22, 11, 8]; const activeUserIds = [1, 4, 22, 11, 8]; const inactiveUserIds = _.difference(allUserIds, activeUserIds); console.log(inactiveUserIds); // [ 3, 2, 10 ] Und was ist, wenn Sie, wie es in einer realistischeren Umgebung der Fall ist, mit einer Reihe von Objekten anstelle von einfachen Primitiven arbeiten müssen? Nun, Lodash hat dafür eine nette differenceBy() Methode!
const allUsers = [ { id: 1, name: 'Phil' }, { id: 2, name: 'John' }, { id: 3, name: 'Rogg' }, ]; const activeUsers = [ { id: 1, name: 'Phil' }, { id: 2, name: 'John' }, ]; const inactiveUsers = _.differenceBy(allUsers, activeUsers, 'id'); console.log(inactiveUsers); // [ { id: 3, name: 'Rogg' } ]Ordentlich, oder?!
Wie der Unterschied gibt es in Lodash andere Methoden für allgemeine Mengenoperationen: Vereinigung, Schnittmenge usw.
Abflachen von Arrays
Die Notwendigkeit, Arrays abzuflachen, tritt häufig auf. Ein Anwendungsfall ist, dass Sie eine API-Antwort erhalten haben und eine map() und filter() Kombination auf eine komplexe Liste verschachtelter Objekte/Arrays anwenden müssen, um beispielsweise Benutzer-IDs herauszusuchen Arrays von Arrays. Hier ist ein Code-Snippet, das diese Situation darstellt:
const orderData = { 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' }, ], }; // find user ids that placed postpaid orders (internal or external) const postpaidUserIds = []; for (const [orderType, orders] of Object.entries(orderData)) { postpaidUserIds.push(orders.filter((order) => order.type === 'postpaid')); } console.log(postpaidUserIds); Können Sie erraten, wie postPaidUserIds jetzt aussieht? Hinweis: Es ist ekelhaft!
[ [], [ { userId: 3, date: '2021-08-08', amount: 30, type: 'postpaid' }, { userId: 4, date: '2021-06-06', amount: 330, type: 'postpaid' } ] ] Wenn Sie ein vernünftiger Mensch sind, möchten Sie keine benutzerdefinierte Logik schreiben, um die Auftragsobjekte zu extrahieren und sie innerhalb eines Arrays schön in einer Reihe anzuordnen. Verwenden Sie einfach die Methode flatten() und genießen Sie die Trauben:
const flatUserIds = _.flatten(postpaidUserIds); console.log(flatUserIds); /* [ { userId: 3, date: '2021-08-08', amount: 30, type: 'postpaid' }, { userId: 4, date: '2021-06-06', amount: 330, type: 'postpaid' } ] */ Beachten Sie, dass flatten() nur eine Ebene tief geht. Das heißt, wenn Ihre Objekte zwei, drei oder mehr Ebenen tief stecken, flatten() sie Sie enttäuschen. In diesen Fällen hat Lodash die Methode flattenDeep() , aber seien Sie 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 Funktionsweise von „falschen“ Werten und Typen in JavaScript führt manchmal etwas so Einfaches wie die Überprüfung auf Leerheit zu existenzieller Angst.

Wie überprüfen Sie, ob ein Array leer ist? Sie können überprüfen, ob seine length 0 oder nicht. Wie überprüfen Sie nun, ob ein Objekt leer ist? Nun... Moment mal! Hier setzt dieses ungute Gefühl ein, und diese JavaScript-Beispiele, die Dinge wie [] == false und {} == false beginnen unsere Köpfe zu kreisen. Wenn Sie unter Druck stehen, ein Feature bereitzustellen, sind Landminen wie diese das Letzte, was Sie brauchen – sie machen Ihren Code schwer verständlich und bringen Unsicherheit in Ihre Testsuite.
Arbeiten mit fehlenden Daten
In der realen Welt hören uns Daten zu; egal wie sehr wir es wollen, es ist selten geradlinig und vernünftig. Ein typisches Beispiel sind fehlende Nullobjekte/Arrays in einer großen Datenstruktur, die als API-Antwort empfangen wird.

Angenommen, wir haben das folgende Objekt als API-Antwort erhalten:
const apiResponse = { id: 33467, paymentRefernce: 'AEE3356T68', // `order` object missing processedAt: `2021-10-10 00:00:00`, }; Wie gezeigt, erhalten wir in der Regel ein order in der Antwort von der API, aber dies 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 order ist, würden wir bald sehr hässlichen Code schreiben, wenn wir Laufzeitfehler vermeiden wollen:
if ( apiResponse.order && apiResponse.order.payee && apiResponse.order.payee.address ) { console.log( 'The order was sent to the zip code: ' + apiResponse.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(apiResponse, 'order.payee.address.zipCode'); console.log('The order was sent to the zip code: ' + zipCode); // The order was sent to the zip code: undefined Es gibt auch die fantastische Option, einen Standardwert bereitzustellen, anstatt für fehlende Dinge undefined zu werden:
const zipCode2 = _.get(apiResponse, 'order.payee.address.zipCode', 'NA'); console.log('The order was sent to the zip code: ' + zipCode2); // The order was sent to the zip code: NA Ich weiß nicht, wie es Ihnen geht, aber get() ist eines dieser Dinge, die mir Freudentränen in die Augen treiben. Es ist nichts Auffälliges. Es gibt keine konsultierte Syntax oder Optionen zum Auswendiglernen, aber sehen Sie sich das Ausmaß des kollektiven Leidens an, das dadurch gelindert werden kann!
Entprellung
Falls Sie es nicht kennen: Entprellen ist ein häufiges Thema in der Frontend-Entwicklung. Die Idee ist, dass es manchmal von Vorteil ist, eine Aktion nicht sofort, sondern nach einiger Zeit (im Allgemeinen ein paar Millisekunden) zu starten. Was bedeutet das? Hier ist ein Beispiel.

Stellen Sie sich eine E-Commerce-Website mit einer Suchleiste vor (jetzt jede Website/Web-App!). 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 bei jedem Tastendruck einen API-Aufruf absetzen, hätten wir einen Albtraum 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 sind irrelevant, da die Benutzereingabe noch nicht abgeschlossen ist.
Die Antwort liegt in der Entprellung, und die Idee ist: Senden Sie keinen API-Aufruf, sobald sich der Text ändert. Warten Sie einige Zeit (z. B. 200 Millisekunden) und wenn bis dahin ein weiterer Tastendruck erfolgt, brechen Sie die frühere Zeitzählung ab und beginnen Sie erneut mit dem Warten. Daher senden wir nur dann eine API-Anfrage an das Back-End, wenn der Benutzer innehält (entweder weil er nachdenkt oder weil er fertig ist und eine Antwort erwartet).
Die von mir beschriebene Gesamtstrategie ist kompliziert, und ich werde mich nicht mit der Synchronisation von Timer-Management und -Abbruch befassen; Der eigentliche Entprellprozess ist jedoch sehr einfach, wenn Sie Lodash verwenden.
const _ = require('lodash'); const axios = require('axios'); // This is a real dogs' API, by the way! const fetchDogBreeds = () => axios .get('https://dog.ceo/api/breeds/list/all') .then((res) => console.log(res.data)); const debouncedFetchDogBreeds = _.debounce(fetchDogBreeds, 1000); // after one second debouncedFetchDogBreeds(); // shows data after some time Wenn Sie an setTimeout() denken, hätte ich den gleichen Job gemacht, nun ja, es gibt noch mehr! Die Entprellung von Lodash verfügt über viele leistungsstarke Funktionen; Sie möchten beispielsweise sicherstellen, dass die Entprellung nicht unbegrenzt ist. Das heißt, selbst wenn jedes Mal, wenn die Funktion ausgelöst wird (und damit der Gesamtprozess abgebrochen wird), ein Tastendruck erfolgt, möchten Sie möglicherweise sicherstellen, dass der API-Aufruf trotzdem nach beispielsweise zwei Sekunden erfolgt. Dafür hat Lodash debounce() die Option maxWait :
const debouncedFetchDogBreeds = _.debounce(fetchDogBreeds, 150, { maxWait: 2000 }); // debounce for 250ms, but send the API request after 2 seconds anywaySehen Sie sich die offiziellen Dokumente an, um einen tieferen Einblick zu erhalten. Sie sind voll mit superwichtigen Sachen!
Werte aus einem Array entfernen
Ich weiß nicht, wie es Ihnen geht, aber ich hasse es, Code zum Entfernen von Elementen aus einem Array zu schreiben. Zuerst muss ich den Index des Elements abrufen, prü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 die ganze Zeit nachschlagen, und am Ende habe ich das nagende Gefühl, dass ich mich irgendeinen dummen Fehler eingeschlichen habe.

const greetings = ['hello', 'hi', 'hey', 'wave', 'hi']; _.pull(greetings, 'wave', 'hi'); console.log(greetings); // [ 'hello', 'hey' ]Bitte beachten Sie zwei Dinge:
- Das ursprüngliche Array wurde dabei verändert.
- Die Methode
pull()entfernt alle Instanzen, auch wenn Duplikate vorhanden sind.
Es gibt eine weitere verwandte Methode namens pullAll() , die ein Array als zweiten Parameter akzeptiert, wodurch es einfacher wird, mehrere Elemente gleichzeitig zu entfernen. Zugegeben, wir könnten einfach pull() mit einem Spread-Operator verwenden, aber denken Sie daran, dass Lodash zu einer Zeit kam, als der Spread-Operator noch nicht einmal ein Vorschlag in der Sprache war!
const greetings2 = ['hello', 'hi', 'hey', 'wave', 'hi']; _.pullAll(greetings2, ['wave', 'hi']); console.log(greetings2); // [ 'hello', 'hey' ]Letzter Index eines Elements
Die native indexOf() Methode von indexOf() ist cool, außer wenn Sie daran interessiert sind, das Array aus der entgegengesetzten Richtung zu scannen! Und noch einmal, ja, Sie könnten 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 integers = [2, 4, 1, 6, -1, 10, 3, -1, 7]; const index = _.lastIndexOf(integers, -1); console.log(index); // 7Leider gibt es keine Variante dieser Methode, mit der wir komplexe Objekte nachschlagen oder sogar eine benutzerdefinierte Nachschlagefunktion übergeben können.
Reißverschluss. Entpacken!

Wenn Sie nicht mit Python gearbeitet haben, ist zip/unzip ein Dienstprogramm, das Sie in Ihrer gesamten Karriere als JavaScript-Entwickler vielleicht nie bemerken oder sich vorstellen können. Und das vielleicht aus gutem Grund: Es gibt selten einen so dringenden Bedarf an zip/unzip wie für filter() usw. Es ist jedoch eines der weniger bekannten Dienstprogramme und kann Ihnen in manchen Situationen dabei helfen, prägnanten Code zu erstellen .
Im Gegensatz zu dem, was es 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 mit Elementen an derselben Position zusammengepackt ( zip() ) und zurück ( unzip() ) umgewandelt werden können. Ja, ich weiß, es wird trüb, mit Worten auszukommen, also schauen wir uns etwas Code an:
const animals = ['duck', 'sheep']; const sizes = ['small', 'large']; const weight = ['less', 'more']; const groupedAnimals = _.zip(animals, sizes, weight); console.log(groupedAnimals); // [ [ 'duck', 'small', 'less' ], [ 'sheep', 'large', 'more' ] ] Die ursprünglichen drei Arrays wurden in ein einziges mit nur zwei Arrays umgewandelt. Und jede dieser neuen Anordnungen repräsentiert ein einzelnes Tier mit all seinen Eigenschaften 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 die Arbeit mit den Daten jetzt einfacher. Nachdem Sie alle erforderlichen Operationen auf die Daten angewendet haben, können Sie sie mit unzip() wieder unzip() und an die ursprüngliche Quelle unzip() :
const animalData = _.unzip(groupedAnimals); console.log(animalData); // [ [ 'duck', 'sheep' ], [ 'small', 'large' ], [ 'less', 'more' ] ]Das Dienstprogramm zip/unzip wird Ihr Leben nicht über Nacht verändern, aber eines Tages wird es Ihr Leben verändern!
Fazit
(Ich habe den gesamten in diesem Artikel verwendeten Quellcode hier eingefügt, damit Sie ihn direkt aus dem Browser ausprobieren können!)
Die Lodash-Dokumentation ist voller Beispiele und Funktionen, die Sie einfach umhauen werden. In einer Zeit, in der der Masochismus im JS-Ökosystem zuzunehmen scheint, ist Lodash wie ein Hauch frischer Luft, und ich empfehle Ihnen dringend, diese Bibliothek in Ihren Projekten zu verwenden!
