Node.js hat sich dank seiner Fähigkeit, JavaScript im Backend zu nutzen, schnell zu einem Standard für die Erstellung von Web-Apps und Systemsoftware entwickelt. Beliebte Frameworks wie Express und Tools wie Webpack tragen zu seiner weiten Verbreitung bei. Obwohl es Konkurrenten wie Deno und Bun gibt, bleibt Node die führende serverseitige JavaScript-Plattform.
Die Multiparadigmennatur von JavaScript ermöglicht verschiedene Programmierstile, birgt jedoch auch Risiken wie Umfangs- und Objektmutationen. Das Fehlen einer Tail-Call-Optimierung macht große rekursive Iterationen gefährlich, und die Single-Threaded-Architektur von Node erfordert aus Effizienzgründen asynchronen Code. Trotz der Herausforderungen kann die Befolgung wichtiger Konzepte und Best Practices in JavaScript Node.js-Entwicklern dabei helfen, skalierbaren und effizienten Code zu schreiben.
1. JavaScript-Abschlüsse
Ein Abschluss in JavaScript ist eine innere Funktion, die Zugriff auf den Umfang ihrer äußeren Funktion hat, auch nachdem die äußere Funktion die Kontrolle zurückgegeben hat. Ein Abschluss macht die Variablen der inneren Funktion privat. Funktionale Programmierung erfreut sich immer größerer Beliebtheit und macht Schließungen zu einem wesentlichen Bestandteil der Node-Entwicklerausrüstung. Hier ist ein einfaches Beispiel für einen Abschluss in JavaScript:
2. JavaScript-Prototypen
Jede JavaScript-Funktion verfügt über eine Prototypeigenschaft, die zum Anhängen von Eigenschaften und Methoden verwendet wird. Diese Eigenschaft ist nicht aufzählbar. Es ermöglicht dem Entwickler, Methoden oder Mitgliedsfunktionen an seine Objekte anzuhängen. JavaScript unterstützt die Vererbung nur über die Prototyp-Eigenschaft. Im Falle eines geerbten Objekts verweist die Prototypeigenschaft auf das übergeordnete Objekt des Objekts. Ein gängiger Ansatz zum Anhängen von Methoden an eine Funktion ist die Verwendung von Prototypen wie hier gezeigt:
Obwohl modernes JavaScript über eine recht ausgefeilte Klassenunterstützung verfügt, nutzt es immer noch das Prototypensystem unter der Haube. Dies ist die Ursache für einen Großteil der Flexibilität der Sprache.
3. Definieren privater Eigenschaften mithilfe von Hash-Namen
Früher wurde die Konvention verwendet, Variablen einen Unterstrich voranzustellen, um anzuzeigen, dass eine Variable privat sein sollte. Dies war jedoch nur ein Vorschlag und keine plattformbedingte Einschränkung. Modernes JavaScript bietet hashtag private Mitglieder und Methoden für Klassen:
Private Hash-Namen sind eine neuere und sehr willkommene Funktion in JavaScript! Aktuelle Node-Versionen und Browser unterstützen es, und Chrome Devtools ermöglicht Ihnen bequemerweise den direkten Zugriff auf private Variablen.
4. Definieren privater Eigenschaften mithilfe von Abschlüssen
Ein anderer Ansatz, den Sie manchmal sehen werden, um das Fehlen privater Eigenschaften im Prototypsystem von JavaScript zu umgehen, ist die Verwendung eines Abschlusses. Mit modernem JavaScript können Sie private Eigenschaften mithilfe des Hashtag-Präfixes definieren, wie im obigen Beispiel gezeigt. Dies funktioniert jedoch nicht für das JavaScript-Prototypsystem. Außerdem ist dies ein Trick, den man häufig im Code findet, und es ist wichtig zu verstehen, was er tut.
Durch das Definieren privater Eigenschaften mithilfe von Abschlüssen können Sie eine private Variable simulieren. Die Mitgliedsfunktionen, die Zugriff auf private Eigenschaften benötigen, sollten im Objekt selbst definiert werden. Hier ist die Syntax zum Erstellen privater Eigenschaften mithilfe von Abschlüssen:
5. JavaScript-Module
Es war einmal, dass JavaScript kein Modulsystem hatte, und Entwickler erfanden einen cleveren Trick (Modulmuster genannt), um etwas zu erstellen, das funktionieren würde. Mit der Weiterentwicklung von JavaScript entstanden nicht nur ein, sondern zwei Modulsysteme: die CommonJS-Syntax include und die ES6-Syntax require.
Node verwendet traditionell CommonJS, während Browser ES6 verwenden. Allerdings unterstützen neuere Versionen von Node (in den letzten Jahren) auch ES6. Der Trend geht jetzt zur Verwendung von ES6-Modulen, und eines Tages werden wir nur noch eine Modulsyntax haben, die wir in JavaScript verwenden können. ES6 sieht so aus (wo wir ein Standardmodul exportieren und es dann importieren):
CommonJS wird weiterhin angezeigt und Sie müssen es manchmal zum Importieren eines Moduls verwenden. So sieht es aus, ein Standardmodul mit CommonJS zu exportieren und dann zu importieren:
6. Fehlerbehandlung
Egal in welcher Sprache oder Umgebung Sie sich befinden, die Fehlerbehandlung ist unerlässlich und unvermeidbar. Node ist keine Ausnahme. Es gibt drei grundlegende Möglichkeiten, mit Fehlern umzugehen: Try/Catch-Blöcke, das Auslösen neuer Fehler und on()-Handler.
Blöcke mit try/catch sind die bewährte Methode zur Fehlererfassung, wenn etwas schief geht:
In diesem Fall protokollieren wir den Fehler mit console.error in der Konsole. Sie können den Fehler auslösen und ihn an den nächsten Handler weitergeben. Beachten Sie, dass dadurch die Ausführung des Codeflusses unterbrochen wird. das heißt, die aktuelle Ausführung stoppt und der nächste Fehlerhandler im Stapel übernimmt:
Modernes JavaScript bietet eine ganze Reihe nützlicher Eigenschaften für seine Error-Objekte, einschließlich Error.stack, um einen Blick auf den Stack-Trace zu werfen. Im obigen Beispiel legen wir die Eigenschaft Error.message und Error.cause mit den Konstruktorargumenten fest.
Fehler finden Sie auch in asynchronen Codeblöcken, in denen Sie normale Ergebnisse mit .then() verarbeiten. In diesem Fall können Sie einen on(‘error’)-Handler oder ein onerror-Ereignis verwenden, je nachdem, wie das Versprechen die Fehler zurückgibt. Manchmal gibt Ihnen die API ein Fehlerobjekt als zweiten Rückgabewert mit dem Normalwert zurück. (Wenn Sie „await“ für den asynchronen Aufruf verwenden, können Sie es in einen Try/Catch einschließen, um etwaige Fehler zu behandeln.) Hier ist ein einfaches Beispiel für die Behandlung eines asynchronen Fehlers:
Egal was passiert, schlucken Sie niemals Fehler herunter! Ich werde das hier nicht zeigen, da es jemand kopieren und einfügen könnte. Grundsätzlich gilt: Wenn Sie einen Fehler erkennen und dann nichts unternehmen, läuft Ihr Programm stillschweigend weiter, ohne dass es offensichtliche Anzeichen dafür gibt, dass etwas schief gelaufen ist. Die Logik wird durchbrochen und Sie müssen grübeln, bis Sie Ihren Fangblock finden, in dem sich nichts befindet. (Beachten Sie, dass die Bereitstellung eines finally{}-Blocks ohne einen Catch-Block dazu führt, dass Ihre Fehler verschluckt werden.)
7. JavaScript-Currying
Currying ist eine Methode, um Funktionen flexibler zu gestalten. Mit einer Curry-Funktion können Sie alle Argumente übergeben, die die Funktion erwartet, und das Ergebnis erhalten, oder Sie können nur eine Teilmenge der Argumente übergeben und eine Funktion zurückerhalten, die auf den Rest der Argumente wartet. Hier ist ein einfaches Beispiel für ein Curry:
Die ursprüngliche Curry-Funktion kann direkt aufgerufen werden, indem jeder Parameter nacheinander in einem separaten Klammersatz übergeben wird:
Dies ist eine interessante Technik, mit der Sie Funktionsfabriken erstellen können, bei denen Sie mit den äußeren Funktionen die innere teilweise konfigurieren können. Sie könnten beispielsweise auch die obige Curry-Funktion wie folgt verwenden:
In der Praxis kann diese Idee hilfreich sein, wenn Sie viele Funktionen erstellen müssen, die je nach bestimmten Parametern variieren.
8. JavaScript-Methoden zum Anwenden, Aufrufen und Binden
Obwohl wir sie nicht jeden Tag verwenden, ist es gut zu verstehen, was die Methoden call, apply und bind sind. Hier haben wir es mit einer erheblichen sprachlichen Flexibilität zu tun. Im Grunde ermöglichen Ihnen diese Methoden, anzugeben, in was das Schlüsselwort dieses aufgelöst wird.
In allen drei Funktionen ist das erste Argument immer der dieser Wert oder Kontext, den Sie der Funktion geben möchten.
Von den dreien ist call am einfachsten. Es ist dasselbe, als würde man eine Funktion aufrufen und gleichzeitig ihren Kontext angeben. Hier ist ein Beispiel:
Beachten Sie, dass apply fast dasselbe ist wie call. Der einzige Unterschied besteht darin, dass Sie Argumente als Array und nicht separat übergeben. Arrays lassen sich in JavaScript einfacher manipulieren, was eine größere Anzahl von Möglichkeiten für die Arbeit mit Funktionen eröffnet. Hier ist ein Beispiel mit apply und call:
Mit der Methode bind können Sie Argumente an eine Funktion übergeben, ohne diese aufzurufen. Eine neue Funktion wird mit begrenzten Argumenten zurückgegeben, die vor allen weiteren Argumenten stehen. Hier ist ein Beispiel:
9. JavaScript-Memoisierung
Memoization ist eine Optimierungstechnik, die die Funktionsausführung beschleunigt, indem Ergebnisse teurer Vorgänge gespeichert und die zwischengespeicherten Ergebnisse zurückgegeben werden, wenn derselbe Satz von Eingaben erneut auftritt. JavaScript-Objekte verhalten sich wie assoziative Arrays, was die Implementierung der Memoisierung in JavaScript erleichtert. So konvertieren Sie eine rekursive Fakultätsfunktion in eine gespeicherte Fakultätsfunktion:
10. JavaScript IIFE
Ein sofort aufgerufener Funktionsausdruck (IIFE) ist eine Funktion, die ausgeführt wird, sobald sie erstellt wird. Es steht in keinem Zusammenhang mit irgendwelchen Ereignissen oder der asynchronen Ausführung. Sie können ein IIFE wie hier gezeigt definieren:
Das erste Klammerpaar function(){...} wandelt den Code innerhalb der Klammern in einen Ausdruck um. Das zweite Klammerpaar ruft die aus dem Ausdruck resultierende Funktion auf. Ein IIFE kann auch als selbstaufrufende anonyme Funktion beschrieben werden. Die häufigste Verwendung besteht darin, den Umfang einer über var erstellten Variablen einzuschränken oder den Kontext zu kapseln, um Namenskollisionen zu vermeiden.
Es gibt auch Situationen, in denen Sie eine Funktion mit await aufrufen müssen, sich aber nicht in einem asynchronen Funktionsblock befinden. Dies passiert manchmal bei Dateien, die direkt ausführbar sein sollen und auch als Modul importiert werden sollen. Sie können einen solchen Funktionsaufruf wie folgt in einen IIFE-Block einschließen:
11. Nützliche Argumentfunktionen
Obwohl JavaScript das Überladen von Methoden nicht unterstützt (da es beliebige Argumentanzahlen für Funktionen verarbeiten kann), verfügt es über mehrere leistungsstarke Funktionen für den Umgang mit Argumenten. Zum einen können Sie eine Funktion oder Methode mit Standardwerten definieren:
Sie können auch alle Argumente gleichzeitig akzeptieren und verarbeiten, sodass Sie eine beliebige Anzahl übergebener Argumente verarbeiten können. Dabei wird der Operator rest verwendet, um alle Argumente in einem Array zu sammeln:
Wenn Sie wirklich mit unterschiedlichen Argumentkonfigurationen zu tun haben, können Sie diese jederzeit überprüfen:
Denken Sie außerdem daran, dass JavaScript ein integriertes Argumentarray enthält. Jede Funktion oder Methode stellt Ihnen automatisch die Variable arguments zur Verfügung, die alle an den Aufruf übergebenen Argumente enthält.
Abschluss
Wenn Sie sich mit Node vertraut machen, werden Sie feststellen, dass es viele Möglichkeiten gibt, fast jedes Problem zu lösen. Der richtige Ansatz ist nicht immer offensichtlich. Manchmal gibt es mehrere gültige Ansätze für eine bestimmte Situation. Es hilft, die vielen verfügbaren Optionen zu kennen.
Die hier besprochenen 10 JavaScript-Konzepte sind Grundlagen, von deren Kenntnis jeder Node-Entwickler profitieren wird. Aber sie sind nur die Spitze des Eisbergs. JavaScript ist eine mächtige und komplexe Sprache. Je öfter Sie es verwenden, desto mehr werden Sie verstehen, wie umfangreich JavaScript wirklich ist und wie viel Sie damit machen können.
Haftungsausschluss: Alle bereitgestellten Ressourcen stammen teilweise aus dem Internet. Wenn eine Verletzung Ihres Urheberrechts oder anderer Rechte und Interessen vorliegt, erläutern Sie bitte die detaillierten Gründe und legen Sie einen Nachweis des Urheberrechts oder Ihrer Rechte und Interessen vor und senden Sie ihn dann an die E-Mail-Adresse: [email protected] Wir werden die Angelegenheit so schnell wie möglich für Sie erledigen.
Copyright© 2022 湘ICP备2022001581号-3