Clever codieren! Werden Sie ein schnellerer, produktiverer und zufriedenerer JavaScript-Entwickler, indem Sie diese wesentlichen und wiederkehrenden Funktionen der Sprache meistern.
Ob Backend oder Frontend (oder sogar Raumschiffe), JavaScript ist allgegenwärtig. Es ist auch eine sehr flexible Sprache (was bedeutet, dass sie sowohl hardcore-funktionale Programmiermuster als auch altbewährte Klassen unterstützt), und ihre Ähnlichkeit mit anderen „C-ähnlichen“ Sprachen erleichtert Entwicklern den Übergang von anderen Sprachen.
Wenn Sie Ihre JavaScript-Kenntnisse verbessern möchten, empfehle ich Ihnen, die folgenden Kernfunktionen der Sprache kennenzulernen, zu üben und schließlich zu beherrschen. Nicht alle davon sind unbedingt für die Lösung von Problemen „erforderlich“, aber sie können in einigen Fällen viel Arbeit für Sie erledigen, während sie in anderen Fällen die Menge an Code reduzieren können, die Sie schreiben müssen.
map()
Es wäre ein Fehler, einen Artikel über wichtige JavaScript-Funktionen zu schreiben, ohne map() zu erwähnen! 😆😆 Zusammen mit filter() und reduce() bildet map() eine Art heilige Dreifaltigkeit. Dies sind Funktionen, die Sie in Ihrer Karriere immer wieder verwenden werden, also sind sie mehr als nur einen Blick wert. Gehen wir sie nacheinander an, beginnend mit map().
map() gehört zu den Funktionen, die JavaScript-Lernenden am meisten Schwierigkeiten bereiten. Warum? Nicht weil sie von Natur aus komplex ist, sondern weil die Art und Weise, wie diese Funktion arbeitet, eine Idee ist, die aus der sogenannten funktionalen Programmierung stammt. Und da wir der funktionalen Programmierung nicht ausgesetzt sind – unsere Schulen und die Industrie sind voll von objektorientierten Sprachen – erscheint uns die Funktionsweise seltsam oder sogar falsch.
JavaScript ist weitaus funktionaler als objektorientiert, obwohl seine modernen Versionen ihr Bestes tun, um diese Tatsache zu verschleiern. Aber das ist ein Fass ohne Boden, das ich vielleicht ein anderes Mal aufmachen kann. 🤣 Okay, also map() . . .
map() ist eine sehr einfache Funktion; sie wird an ein Array angehängt und hilft uns, jedes Element in etwas anderes umzuwandeln, was zu einem neuen Array führt. Wie genau ein Element umgewandelt wird, wird durch eine weitere Funktion vorgegeben, die in der Regel anonym ist.
Das ist alles dazu! Die Syntax mag etwas gewöhnungsbedürftig sein, aber im Wesentlichen tun wir das in einer map()-Funktion. Warum sollten wir map() verwenden? Das hängt davon ab, was wir erreichen wollen. Nehmen wir an, wir haben die Temperatur für jeden Tag der letzten Woche aufgezeichnet und als einfaches Array gespeichert. Nun wird uns jedoch mitgeteilt, dass die Instrumente nicht sehr genau waren und 1,5 Grad weniger Temperatur gemeldet haben, als sie hätten melden sollen.
Wir können diese Korrektur mit der Funktion map() wie folgt vornehmen:
const weeklyReadings = [20, 22, 20.5, 19, 21, 21.5, 23];
const correctedWeeklyReadings = weeklyReadings.map(reading => reading + 1.5);
console.log(correctedWeeklyReadings); // gibt [ 21.5, 23.5, 22, 20.5, 22.5, 23, 24.5 ]
Ein weiteres, sehr praktisches Beispiel stammt aus der Welt von React, wo das Erstellen von DOM-Elementlisten aus Arrays ein gängiges Muster ist; also ist so etwas üblich:
export default ({ products }) => {
return products.map(product => {
return (
<div className="product" key={product.id}>
<div className="p-name">{product.name}</div>
<div className="p-desc">{product.description}</div>
</div>
);
});
};
Hier haben wir eine funktionale React-Komponente, die eine Liste von Produkten als Eigenschaften erhält. Aus dieser Liste (einem Array) erstellt sie dann eine Liste von HTML-„divs“, die im Grunde jedes Produktobjekt in HTML umwandeln. Das ursprüngliche Produktobjekt bleibt unberührt.
Sie könnten argumentieren, dass map() nichts anderes als eine verherrlichte for-Schleife ist, und Sie hätten vollkommen Recht. Aber beachten Sie, dass, sobald Sie dieses Argument vorbringen, Ihr objektorientiert geschultes Gehirn spricht, während diese Funktionen und ihr zugrunde liegendes Prinzip aus der funktionalen Programmierung stammen, wo Einheitlichkeit, Kompaktheit und Eleganz hoch geschätzt werden. 🙂
filter()
filter() ist eine äußerst nützliche Funktion, die Sie in vielen Situationen immer wieder verwenden werden. Wie der Name schon sagt, filtert diese Funktion ein Array anhand der von Ihnen angegebenen Regeln/Logik und gibt ein neues Array zurück, das Elemente enthält, die diese Regeln erfüllen.
Nehmen wir wieder unser Wetterbeispiel. Nehmen wir an, wir haben ein Array mit den Höchsttemperaturen für jeden Tag der letzten Woche; nun wollen wir herausfinden, an wie vielen dieser Tage es kälter war. Ja, „kälter“ ist ein subjektiver Begriff, also sagen wir, wir suchen nach Tagen, an denen die Temperatur unter 20 Grad lag. Wir können dies mit der Funktion filter() wie folgt tun:
const weeklyReadings = [20, 22, 20.5, 19, 21, 21.5, 23];
const colderDays = weeklyReadings.filter(dayTemperature => {
return dayTemperature < 20;
});
console.log("Total colder days in week were: " + colderDays.length); // 1
Beachten Sie, dass die anonyme Funktion, die wir an filter() übergeben, einen booleschen Wert zurückgeben muss: wahr oder falsch. Auf diese Weise weiß filter(), ob dieses Element in das gefilterte Array aufgenommen werden soll oder nicht. Es steht Ihnen frei, beliebig komplexe Logik in diese anonyme Funktion zu schreiben; Sie können API-Aufrufe tätigen und Benutzereingaben lesen usw., solange Sie sicherstellen, dass Sie am Ende einen booleschen Wert zurückgeben.
Achtung: Dies ist eine Randbemerkung, die ich aufgrund meiner Erfahrung als JavaScript-Entwickler geben möchte. Ob aus Nachlässigkeit oder falschen Grundlagen, viele Programmierer erzeugen subtile Fehler in ihren Programmen, wenn sie filter() verwenden. Schreiben wir den vorherigen Code um, um den Fehler einzudämmen:
const weeklyReadings = [20, 22, 20.5, 19, 21, 21.5, 23];
const colderDays = weeklyReadings.filter(dayTemperature => {
return dayTemperature < 20;
});
if(colderDays) {
console.log("Yes, there were colder days last week");
} else {
console.log("No, there were no colder days");
}
Fällt Ihnen etwas auf? Gut gemacht, wenn Sie es getan haben! Die if-Bedingung am Ende überprüft colderDays, was eigentlich ein Array ist! Sie werden überrascht sein, wie oft Menschen diesen Fehler machen, wenn sie versuchen, Fristen einzuhalten oder in schlechter Stimmung zu programmieren (aus welchen Gründen auch immer). Das Problem bei dieser Bedingung ist, dass JavaScript in vielerlei Hinsicht eine seltsame und inkonsistente Sprache ist, und die „Wahrheit“ der Dinge ist eine davon. Während [] == true false zurückgibt, was Sie glauben lässt, dass der obige Code nicht fehlerhaft ist, ist die Realität, dass innerhalb einer if-Bedingung [] als wahr ausgewertet wird! Mit anderen Worten, der Code, den wir geschrieben haben, wird niemals aussagen, dass es letzte Woche keine kälteren Tage gab.
Die Lösung ist sehr einfach, wie im Code vor dem obigen Code angegeben. Wir suchen nach colderDays.length, was uns garantiert eine ganze Zahl (null oder höher) liefert und daher in logischen Vergleichen konsistent arbeitet. Beachten Sie, dass filter() immer, immer, immer ein leeres oder nicht leeres Array zurückgibt, sodass wir uns darauf verlassen und unsere logischen Vergleiche sicher schreiben können.
Das war ein längerer Exkurs, als ich geplant hatte, aber Fehler wie dieser sind es wert, in zehntausend Worten hervorgehoben zu werden, wenn nötig in Großbuchstaben. Ich hoffe, dass Sie davon verschont bleiben und sich Hunderte von Stunden Debugging-Aufwand ersparen! 🙂
reduce()
Von allen Funktionen in diesem Artikel sowie in der Standard-JavaScript-Bibliothek gehört reduce() zu den Spitzenreitern für die Krone von „verwirrend und seltsam“. Obwohl diese Funktion sehr wichtig ist und in vielen Situationen zu elegantem Code führt, wird sie von den meisten JavaScript-Entwicklern vermieden, die stattdessen lieber ausführlichen Code schreiben.
Der Grund ist, dass – und ich werde hier ehrlich sein! – reduce() ist sowohl im Sinne des Konzepts als auch der Ausführung schwer zu verstehen. Wenn Sie seine Beschreibung lesen, haben Sie sie wahrscheinlich mehrmals gelesen und bezweifeln immer noch, dass Sie sie richtig gelesen haben; und wenn Sie es in Aktion sehen und versuchen, sich vorzustellen, wie es funktioniert, dreht sich Ihr Gehirn in tausend Knoten! 🤭
Jetzt keine Angst. Die Funktion reduce() ist in ihrer Komplexität und Einschüchterung bei weitem nicht so anspruchsvoll wie beispielsweise B+ Bäume und ihre Algorithmen. Es ist nur so, dass diese Art von Logik im Alltag eines durchschnittlichen Programmierers selten anzutreffen ist.
Nachdem ich Sie zu Tode erschreckt und Ihnen sofort gesagt habe, dass Sie sich keine Sorgen machen sollen, möchte ich Ihnen endlich zeigen, was diese Funktion ist und warum genau wir sie brauchen könnten.
Wie der Name schon sagt, wird reduce() verwendet, um etwas zu reduzieren. Das Ding, das sie reduziert, ist ein Array, und das Ding, auf das sie das gegebene Array reduziert, ist ein einzelner Wert (Zahl, Zeichenkette, Funktion, Objekt, was auch immer). Hier ist eine einfachere Art, es auszudrücken – reduce() wandelt ein Array in einen einzelnen Wert um. Beachten Sie, dass der Rückgabewert von reduce() kein Array ist, wie bei map() und filter(). So viel verstanden zu haben, ist schon die halbe Miete. 🙂
Nun, es ist ziemlich offensichtlich, dass wir, wenn wir ein Array transformieren (reduzieren) wollen, die notwendige Logik bereitstellen müssen; und aufgrund Ihrer Erfahrung als JS-Entwickler haben Sie wahrscheinlich schon erraten, dass wir das mit einer Funktion tun. Diese Funktion nennen wir die Reduzierfunktion, die das erste Argument für reduce() bildet. Das zweite Argument ist ein Startwert, wie eine Zahl, eine Zeichenkette usw. (ich werde gleich erklären, was zum Teufel dieser „Startwert“ ist).
Basierend auf unserem bisherigen Verständnis können wir sagen, dass ein Aufruf von reduce() so aussieht: array.reduce(reducerFunction, StartingValue). Kommen wir nun zum Kern des Ganzen: der Reduzierfunktion. Wie bereits festgestellt, ist es die Reduzierfunktion, die reduce() mitteilt, wie das Array in einen einzelnen Wert konvertiert werden soll. Sie benötigt zwei Argumente: eine Variable, die als Akkumulator dient (keine Sorge, ich werde auch dieses Detail erklären), und eine Variable, um den aktuellen Wert zu speichern.
Ich weiß, ich weiß . . . Das war eine Menge Terminologie für eine einzige Funktion, die in JavaScript nicht einmal obligatorisch ist. 😝😝 Und deshalb laufen die Leute vor reduce() weg. Aber wenn Sie es Schritt für Schritt lernen, werden Sie es nicht nur verstehen, sondern auch zu schätzen wissen, wenn Sie ein besserer Entwickler werden.
Okay, also zurück zum eigentlichen Thema. Der „Startwert“, der an reduce() übergeben wird, ist . . . nun, der Startwert für die Berechnung, die Sie verwenden möchten. Wenn Sie beispielsweise in der Reduzierfunktion multiplizieren wollen, ist ein Startwert von 1 sinnvoll; für die Addition könnten Sie mit 0 beginnen und so weiter.
Schauen wir uns nun die Signatur für die Reduzierfunktion an. Eine an reduce() übergebene Reduzierfunktion hat die folgende Form: Reduzierfunktion(Akkumulator, aktuellerWert). „Akkumulator“ ist nur ein ausgefallener Name für die Variable, die das Ergebnis der Berechnung sammelt und speichert; es ist genau so, als würde man eine Variable namens total verwenden, um alle Elemente in einem Array mit etwas wie total += arr[i] zu addieren. Genau so wird die Reduzierfunktion in reduce() angewendet: Der Akkumulator wird zunächst auf den von Ihnen angegebenen Startwert gesetzt, und dann werden nacheinander die Elemente im Array besucht, die Berechnung durchgeführt und das Ergebnis im Akkumulator gespeichert usw. . . .
Was ist also dieser „aktuelle Wert“ in einer Reduzierfunktion? Es ist die gleiche Idee, die Sie sich vorstellen würden, wenn ich Sie auffordern würde, ein Array zu durchlaufen: Sie würden eine Variable nehmen, um bei Index Null zu beginnen, und sie Schritt für Schritt vorwärts bewegen. Wenn ich Sie währenddessen bitten würde, plötzlich aufzuhören, würden Sie sich an einem der Elemente des Arrays wiederfinden, richtig? Das meinen wir mit aktuellem Wert: Es ist der Wert der Variablen, die verwendet wird, um das gerade betrachtete Array-Element darzustellen (denken Sie daran, ein Array zu durchlaufen, wenn das hilft).
Nach alledem ist es an der Zeit, sich ein einfaches Beispiel anzusehen und zu sehen, wie all dieser Jargon in einem tatsächlichen reduce()-Aufruf zusammenkommt. Nehmen wir an, wir haben ein Array mit den ersten n natürlichen Zahlen (1, 2, 3 . . . n) und wir möchten die Fakultät von n finden. Wir wissen, dass wir zum Finden von n! einfach alles multiplizieren müssen, was uns zu dieser Implementierung führt:
const numbers = [1, 2, 3, 4, 5];
const factorial = numbers.reduce((acc, item) => acc * item, 1);
console.log(factorial); // 120
In diesen nur drei Codezeilen passiert viel, also packen wir es nacheinander im Kontext der (sehr langen) Diskussion, die wir bisher geführt haben. Wie offensichtlich ist, ist numbers das Array, das alle Zahlen enthält, die wir multiplizieren möchten. Betrachten Sie als Nächstes den Aufruf numbers.reduce(), der besagt, dass der Startwert für acc 1 sein sollte (weil er keine Multiplikation beeinflusst oder zerstört). Betrachten Sie als Nächstes den Rumpf der Reduzierfunktion, `(acc, item) => acc * item`, der einfach besagt, dass der Rückgabewert für jede Iteration über das Array dieses Element sein sollte, multipliziert mit dem, was sich bereits im Akkumulator befindet. Die Iteration und die eigentliche explizite Speicherung der Multiplikation im Akkumulator ist das, was hinter den Kulissen passiert, und das ist einer der Hauptgründe, warum reduce() für JavaScript-Entwickler so ein Stolperstein ist.
Warum reduce() verwenden?
Das ist eine wirklich gute Frage, und um ehrlich zu sein, habe ich keine sichere Antwort. Was auch immer reduce() tut, kann durch Schleifen, forEach() usw. ausgeführt werden. Diese Techniken führen jedoch zu viel mehr Code, was das Lesen erschwert, besonders wenn Sie es eilig haben. Dann ist da noch die Sorge um die Unveränderlichkeit: Mit reduce() und ähnlichen Funktionen können Sie sicher sein, dass Ihre Originaldaten nicht verändert wurden; dies allein beseitigt ganze Klassen von Fehlern, insbesondere in verteilten Anwendungen.
Schließlich ist reduce() viel flexibler, in dem Sinne, dass der Akkumulator ein Objekt, ein Array oder sogar eine Funktion sein kann, falls erforderlich; das Gleiche gilt für den Startwert und andere Teile des Funktionsaufrufs – fast alles kann hinein und fast alles kann herauskommen, also gibt es extreme Flexibilität beim Entwerfen von wiederverwendbarem Code.
Wenn Sie immer noch nicht überzeugt sind, ist das auch völlig in Ordnung; die JavaScript-Community selbst ist scharf gespalten über die „Kompaktheit“, „Eleganz“ und „Kraft“ von reduce(), also ist es in Ordnung, wenn Sie es nicht verwenden. 🙂 Aber schauen Sie sich unbedingt einige nette Beispiele an, bevor Sie sich entscheiden, reduce() den Rücken zu kehren.
some()
Angenommen, Sie haben ein Array von Objekten, wobei jedes Objekt eine Person darstellt. Sie möchten wissen, ob es im Array Personen gibt, die älter als 35 Jahre sind. Beachten Sie, dass es nicht nötig ist zu zählen, wie viele solcher Personen es gibt, geschweige denn, eine Liste von ihnen abzurufen. Was wir hier sagen, ist das Äquivalent von „einem oder mehreren“ oder „mindestens einem“.
Wie würden Sie das anstellen?
Ja, Sie könnten eine Flag-Variable erstellen und das Array durchlaufen, um dieses Problem wie folgt zu lösen:
const persons = [
{
name: 'Person 1',
age: 32
},
{
name: 'Person 2',
age: 40
},
];
let foundOver35 = false;
for (let i = 0; i < persons.length; i ++) {
if(persons[i].age > 35) {
foundOver35 = true;
break;
}
}
if(foundOver35) {
console.log("Yup, there are a few people here!")
}
Das Problem? Der Code ist meiner Meinung nach zu C- oder Java-ähnlich. „Ausführlich“ ist ein anderes Wort, das mir in den Sinn kommt. Erfahrene JS-Entwickler denken vielleicht an „hässlich“, „schrecklich“ usw. 😝 Zu Recht, würde ich sagen. Eine Möglichkeit, diesen Code zu verbessern, besteht darin, so etwas wie map() zu verwenden, aber selbst dann ist die Lösung etwas umständlich.
Es stellt sich heraus, dass wir eine ziemlich nette Funktion namens some() haben, die bereits in der Kernsprache verfügbar ist. Diese Funktion arbeitet mit Arrays und akzeptiert eine benutzerdefinierte „Filter“-Funktion, die einen booleschen Wert von wahr oder falsch zurückgibt. Im Wesentlichen macht sie das, was wir in den letzten Minuten versucht haben, nur sehr prägnant und elegant. So können wir sie verwenden:
const persons = [
{
name: 'Person 1',
age: 32
},
{
name: 'Person 2',
age: 40
},
];
if(persons.some(person => {
return person.age > 35
})) {
console.log("Found some people!")
}
Gleiche Eingabe, gleiches Ergebnis wie zuvor; aber beachten Sie die massive Reduzierung des Codes! Beachten Sie auch, wie drastisch die kognitive Belastung reduziert wird, da wir den Code nicht mehr Zeile für Zeile analysieren müssen, als ob wir selbst der Interpreter wären! Der Code liest sich jetzt fast wie natürliche Sprache.
every()
Genau wie some() haben wir eine weitere nützliche Funktion namens every(). Wie Sie sich inzwischen denken können, gibt auch diese einen booleschen Wert zurück, je nachdem, ob alle Elemente im Array den gegebenen Test bestehen. Natürlich wird der Test zum Bestehen meistens als anonyme Funktion bereitgestellt. Ich erspare Ihnen den Schmerz, wie eine naive Version des Codes aussehen könnte, also wird every() wie folgt verwendet:
const entries = [
{
id: 1
},
{
id: 2
},
{
id: 3
},
];
if(entries.every(entry => {
return Number.isInteger(entry.id) && entry.id > 0;
})) {
console.log("All the entries have a valid id")
}
Wie offensichtlich ist, überprüft der Code alle Objekte im Array auf eine gültige ID-Eigenschaft. Die Definition von „gültig“ hängt vom Problemkontext ab, aber wie Sie sehen können, habe ich für diesen Code keine negativen ganzen Zahlen berücksichtigt. Wieder einmal sehen wir, wie einfach und elegant der Code zu lesen ist, was das einzige Ziel dieser (und ähnlicher) Funktion(en) ist.
includes()
Wie überprüfen Sie die Existenz von Teilstrings und Array-Elementen? Nun, wenn Sie wie ich sind, greifen Sie schnell nach indexOf() und schlagen dann die Dokumentation nach, um sich über die möglichen Rückgabewerte zu informieren. Es ist eine beträchtliche Unannehmlichkeit, und die Rückgabewerte sind schwer zu merken (schnell – was bedeutet ein Prozess, der 2 an das Betriebssystem zurückgibt?).
Aber es gibt eine nette Alternative, die wir verwenden können: include(). Die Verwendung ist so einfach wie der Name, und der resultierende Code ist äußerst herzerwärmend. Denken Sie daran, dass beim Abgleich von include() die Groß- und Kleinschreibung beachtet wird, aber ich denke, das ist es, was wir alle intuitiv erwarten. Und nun, Zeit für etwas Code!
const numbers = [1, 2, 3, 4, 5];
console.log(numbers.includes(4));
const name = "Ankush";
console.log(name.includes('ank')); // false, weil der erste Buchstabe klein geschrieben ist
console.log(name.includes('Ank')); // true, wie erwartet
Erwarten Sie jedoch nicht zu viel von dieser bescheidenen Methode:
const user = {a: 10, b: 20};
console.log(user.includes('a')); // geht schief, da Objekte keine "includes"-Methode haben
Es kann nicht in Objekte hineinschauen, da es einfach nicht für Objekte definiert ist. Aber hey, wir wissen, dass es auf Arrays funktioniert, also können wir hier vielleicht ein paar Tricks anwenden. . . 🤔.
const persons = [{name: 'Phil'}, {name: 'Jane'}];
persons.includes({name: 'Phil'});
Was passiert also, wenn Sie diesen Code ausführen? Er geht nicht schief, aber die Ausgabe ist auch enttäuschend: false. 😫😫 Eigentlich hat das mit Objekten, Zeigern und der Art und Weise zu tun, wie JavaScript Speicher sieht und verwaltet, was eine eigene Welt ist. Wenn Sie tiefer eintauchen möchten, können Sie den Sprung wagen (vielleicht starten Sie hier), aber ich höre hier auf.
Wir können den obigen Code dazu bringen, sich so zu verhalten, wenn wir ihn wie folgt umschreiben, aber an diesem Punkt wird er meiner Meinung nach mehr oder weniger zu einem Witz:
const phil = {name: 'Phil'};
const persons = [phil, {name: 'Jane'}];
persons.includes(phil); // true
Dennoch zeigt es, dass wir include() auf Objekten zum Laufen bringen können, also denke ich, dass es keine totale Katastrophe ist. 😄
slice()
Angenommen, wir haben eine Zeichenkette, und ich bitte Sie, einen Teil davon zurückzugeben, der mit „r“ beginnt und mit „z“ endet (die tatsächlichen Zeichen sind nicht wichtig). Wie würden Sie es angehen? Vielleicht würden Sie eine neue Zeichenkette erstellen und diese verwenden, um alle erforderlichen Zeichen zu speichern und sie zurückzugeben. Oder wenn Sie wie die meisten Programmierer sind, würden Sie mir im Gegenzug zwei Array-Indizes geben: einen, der den Anfang des Teilstrings anzeigt, der andere, der das Ende markiert.
Beide Ansätze sind in Ordnung, aber es gibt ein Konzept namens Slicing, das in solchen Situationen eine nette Lösung bietet. Zum Glück gibt es keine abstruse Theorie, der man folgen muss; Slicing bedeutet genau das, wonach es sich anhört – das Erstellen einer kleineren Zeichenkette/eines kleineren Arrays aus dem gegebenen, ähnlich wie wir Obstscheiben erstellen. Mal sehen, was ich meine, mit Hilfe eines einfachen Beispiels:
const headline = "And in tonight's special, the guest we've all been waiting for!";
const startIndex = headline.indexOf('guest');
const endIndex = headline.indexOf('waiting');
const newHeadline = headline.slice(startIndex, endIndex);
console.log(newHeadline); // guest we've all been
Wenn wir slice() verwenden, stellen wir JavaScript zwei Indizes zur Verfügung – einen, an dem wir mit dem Slicing beginnen möchten, und einen, an dem es enden soll. Der Haken an slice() ist, dass der Endindex nicht im Endergebnis enthalten ist, weshalb wir sehen, dass das Wort „waiting“ in der neuen Überschrift im obigen Code fehlt.
Konzepte wie Slicing sind in anderen Sprachen, insbesondere in Python, stärker verbreitet. Wenn Sie diese Entwickler fragen, werden sie sagen, dass sie sich ein Leben ohne diese Funktionalität nicht vorstellen können, und das zu Recht, wenn die Sprache eine sehr ordentliche Syntax für das Slicing bietet.
Das Slicing ist ordentlich und äußerst praktisch, und es gibt keinen Grund, es nicht zu verwenden. Es ist auch kein Syntaxzucker, der mit einer Leistungseinbuße durchsetzt ist, da es flache Kopien des ursprünglichen Arrays/Strings erstellt. JavaScript-Entwicklern empfehle ich dringend, sich mit slice() vertraut zu machen und es Ihrem Arsenal hinzuzufügen!
splice()
Die Methode splice() klingt wie ein Cousin von slice(), und in gewisser Weise können wir argumentieren, dass sie es ist. Beide erstellen neue Arrays/Strings aus den ursprünglichen, mit einem kleinen, aber wichtigen Unterschied – splice() entfernt, ändert oder fügt Elemente hinzu, modifiziert aber das ursprüngliche Array. Diese „Zerstörung“ des ursprünglichen Arrays kann zu großen Problemen führen, wenn Sie nicht aufpassen oder tiefe Kopien und Referenzen nicht verstehen. Ich frage mich, was die Entwickler davon abgehalten hat, den gleichen Ansatz wie für slice() zu verwenden und das ursprüngliche Array unberührt zu lassen, aber ich denke, wir können einer Sprache nachsichtiger sein, die in nur zehn Tagen erstellt wurde.
Lassen Sie uns ungeachtet meiner Beschwerden einen Blick darauf werfen, wie splice() funktioniert. Ich zeige ein Beispiel, in dem wir einige Elemente aus einem Array entfernen, da dies die häufigste Verwendung für diese Methode ist. Ich werde auch darauf verzichten, Beispiele für Addition und Einfügung zu geben, da diese leicht nachzuschlagen und ebenfalls einfach sind.
const items = ['eggs', 'milk', 'cheese', 'bread', 'butter'];
items.splice(2, 1);
console.log(items); // [ 'eggs', 'milk', 'bread', 'butter' ]
Der obige Aufruf von splice() besagt: Beginnen Sie bei Index 2 (d. h. an der dritten Stelle) des Arrays und entfernen Sie ein Element. Im gegebenen Array ist „Käse“ das dritte Element, also wird es aus dem Array entfernt und das Array der Elemente wird wie erwartet gekürzt. Übrigens werden die entfernten Elemente von splice() in der Form eines Arrays zurückgegeben. Wenn wir also wollten, hätten wir „Käse“ in einer Variablen erfassen können.
Meiner Erfahrung nach haben indexOf() und splice() eine großartige Synergie – wir finden den Index eines Elements und entfernen es dann aus dem angegebenen Array. Beachten Sie jedoch, dass dies nicht immer die effizienteste Methode ist und dass die Verwendung von Objektschlüsseln (das Äquivalent einer Hash-Map) häufig viel schneller ist.
shift()
shift() ist eine sehr praktische Methode und wird verwendet, um das erste Element eines Arrays zu entfernen. Beachten Sie, dass das Gleiche mit splice() gemacht werden kann, aber shift() ist etwas einfacher zu merken und intuitiver, wenn Sie nur das erste Element abschneiden müssen.
const items = ['eggs', 'milk', 'cheese', 'bread', 'butter'];
items.shift()
console.log(items); // [ 'milk', 'cheese', 'bread', 'butter' ]
unshift()
So wie shift() das erste Element aus einem Array entfernt, fügt unshift() ein neues Element am Anfang des Arrays hinzu. Genauso einfach und kompakt ist seine Anwendung:
const items = ['eggs', 'milk'];
items.unshift('bread')
console.log(items); // [ 'bread', 'eggs', 'milk' ]
Trotzdem kann ich mir nicht helfen und warne diejenigen, die neu im Spiel sind: Im Gegensatz zu den beliebten push()- und pop()-Methoden sind shift() und unshift() extrem ineffizient (aufgrund der Art und Weise, wie die zugrunde liegenden Algorithmen funktionieren). Wenn Sie also mit großen Arrays arbeiten (z. B. über 2000 Elemente), können zu viele dieser Funktionsaufrufe Ihre Anwendung zum Erliegen bringen.
fill()
Manchmal müssen Sie mehrere Elemente auf einen einzigen Wert ändern oder sogar das gesamte Array sozusagen „zurücksetzen“. In diesen Situationen bewahrt Sie fill() vor Schleifen und Off-by-One-Fehlern. Es kann verwendet werden, um einen Teil oder das gesamte Array durch den angegebenen Wert zu ersetzen. Sehen wir uns ein paar Beispiele an:
const heights = [1, 2, 4, 5, 6, 7, 1, 1];
heights.fill(0);
console.log(heights); // [0, 0, 0, 0, 0, 0, 0, 0]
const heights2 = [1, 2, 4, 5, 6, 7, 1, 1];
heights2.fill(0, 4);
console.log(heights2); // [1, 2, 4, 5, 0, 0, 0, 0]
Weitere erwähnenswerte Funktionen
Während die obige Liste das ist, was die meisten JavaScript-Entwickler in ihrer Karriere begegnen und verwenden, ist sie keineswegs vollständig. Es gibt so viele weitere kleinere, aber nützliche Funktionen (Methoden) in JavaScript, dass es nicht möglich sein wird, sie alle in einem einzigen Artikel zu behandeln. Davon abgesehen, ein paar, die mir in den Sinn kommen, sind die folgenden:
- reverse()
- sort()
- entries()
- fill()
- find()
- flat()
Ich ermutige Sie, diese zumindest nachzuschlagen, damit Sie eine Vorstellung davon haben, dass es solche Annehmlichkeiten gibt.
Fazit
JavaScript ist eine große Sprache, trotz der geringen Anzahl von Kernkonzepten, die es zu lernen gilt. Die vielen Funktionen (Methoden), die uns zur Verfügung stehen, machen den Großteil dieser Größe aus. Da JavaScript jedoch für die meisten Entwickler eine Zweitsprache ist, tauchen wir nicht tief genug ein und verpassen viele schöne und nützliche Funktionen, die es bietet. Eigentlich gilt dasselbe für funktionale Programmierkonzepte, aber das ist ein Thema für einen anderen Tag! 😅
Wann immer Sie können, verbringen Sie etwas Zeit damit, die Kernsprache zu erkunden (und, wenn möglich, berühmte Hilfsbibliotheken wie Lodash). Selbst ein paar Minuten, die Sie für diesen Aufwand aufwenden, führen zu massiven Produktivitätssteigerungen und einem weitaus saubereren und kompakteren Code.