Vereinfachen Sie Ihr JavaScript mit CoffeeScript

Dieser Artikel erschien zuerst in Ausgabe 221 of .net magazine - das weltweit meistverkaufte Magazin für Webdesigner und Entwickler.

JavaScript ist nicht sehr gut lesbar und unlesbarer Code ist schwer zu pflegen. Im Vergleich zu Ruby oder Python gibt es überall Klammern, Klammern und Anführungszeichen. Oft gibt es mehr Syntax als Software.

Eingeben CoffeeScript . Es ist kein Framework, sondern wird zu ausführbarem JavaScript kompiliert. Sie schreiben CoffeeScript, kompilieren es und veröffentlichen sauberes, straffes JavaScript, das für den Browser bereit ist. Sie erhalten optimiertes JavaScript, arbeiten jedoch mit sauberem, verständlichem und wartbarem Code.

Sobald Sie einige geschrieben haben, macht CoffeeScript wirklich Sinn. Lassen Sie uns also loslegen. Zuerst installieren wir den CoffeeScript-Compiler und lassen unsere CoffeeScript-Dateien in JavaScript konvertieren, das wir in unseren Browser laden können.

Um CoffeeScript auf Ihrem Entwicklungscomputer zu installieren, benötigen Sie eine * nix-ähnliche Umgebung, einen Texteditor, ein Terminal und einen Browser, um die Ergebnisse zu überprüfen. Zuerst installieren wir node.js (eine JavaScript-Laufzeit, die CoffeeScript benötigt, um seine Magie zu entfalten). Anschließend installieren wir den Paketmanager des Knotens (npm) und installieren damit CoffeeScript selbst. Unter OS X ist dies mit Homebrew am einfachsten. Stellen Sie sicher, dass Sie XCode installiert haben, und befolgen Sie die Anweisungen zum Installieren von Homebrew, oder öffnen Sie einfach eine Terminalsitzung und geben Sie Folgendes ein:

/usr/bin/ruby -e '$(curl -fsSL https://raw.github.com/gist/323731)'Install node.js: brew install node

dann npm und CoffeeScript:



curl http://npmjs.org/install.sh | sh npm install -g coffee-script

Wenn Sie Linux ausführen, kann Ihr Paketmanager Node installieren und anschließend npm und CoffeeScript installieren. Wenn Sie andererseits Windows verwenden, befolgen Sie die Anweisungen von Matthew Podwysocki unter CodeBetter . In diesem Tutorial dreht sich alles um die CoffeeScript-Syntax. Lassen Sie uns das Projektziel einfach halten: Aktivieren Sie die clientseitige Validierung in einem Formular. Hier ist unser Formular in index.html ::

  1. Name
  2. Email
  3. Enquiry

Wir haben auch ein Verzeichnis, Skript , enthält eine leere Datei namens form.coffee .

Besser aussehend: CoffeeScript

Besser aussehend: Der Code von CoffeeScript ist verständlicher als der von Vanille-JavaScript

Das Wasser kochen

Schreiben wir CoffeeScript! Öffnen Sie form.coffee und fügen Sie Folgendes hinzu:

required_field_names = ['name','email']

Bisher nur JavaScript, aber es ist ein Anfang. Kompilieren wir form.coffee . Öffnen Sie ein Terminal und eine CD in das Skriptverzeichnis:

cd public/script

Das Kaffee-Dienstprogramm von CoffeeScript kann die Datei kompilieren:

coffee -c form.coffee

Das -c Das Flag weist Coffee an, das CoffeeScript in eine Datei zu kompilieren. Ohne sie kompiliert Kaffee die Datei und führt sie aus. -c schreibt JavaScript in eine Datei namens form.js , im selben Verzeichnis wie die form.coffee Datei. Schauen wir uns das an form.js ::

(function() { var required_field_names; required_field_names = ['name', 'email']; }).call(this);

Was passiert ist? Das Erforderliche_Feldnamen Die Variable wurde von var festgelegt, und das gesamte Skript wurde in einen Namespace eingeschlossen. Dies schützt uns vor einer der häufigsten Fehlerquellen in JavaScript: versehentliche globale Variablen. In CoffeeScript sind Variablen standardmäßig lokal und nicht global wie in normalem JavaScript. Wenn Sie sich noch nie Gedanken über das Scoping in JavaScript gemacht haben, haben Sie großes Glück. Wenn ja, dann ist dies ein Lebensretter.

Der erste Schluck

Nehmen wir unser JavaScript in auf index.html ::

und aktualisieren Sie das Formular, um beim Senden eine Funktion aufzurufen:

Deklarieren wir unser Array für erforderliche Felder in dieser Validierungsfunktion und geben false zurück, um zu verhindern, dass das Formular während der Entwicklung gesendet wird. In JS könnten wir Folgendes tun:

Death Store Horror Kunst und Design
var validate = function(form) { var required_field_names = ['name','email']; return false; }

Mit CoffeeScript können wir verlieren wo Anruf. Zusätzlich:

function ( args ) {

wird:

(args) ->

Anstelle von geschweiften Klammern verwenden wir Einrückungen, um den Inhalt der Funktion zu definieren:

validate = (form) -> required_field_names = ['name','email'] return false

Beachten Sie, dass wir auch nachfolgende Semikolons entfernt haben. Ein letzter Trick: CoffeeScript gibt das Ergebnis des letzten Ausdrucks in einer Funktion zurück, sodass wir die Rückgabe verlieren können:

validate = (form) -> required_field_names = ['name','email'] false

Kompilieren:

coffee -c form.coffee

und schau dir an form.js überprüfen. Laden Sie unser Formular neu, klicken Sie auf Senden und ... das Formular wird gesendet. Was ist falsch gelaufen?

CoffeeScript erstellt alles in einem Namespace und mit lokalem Gültigkeitsbereich. Das bedeutet, dass während bestätigen ist für alles innerhalb verfügbar form.coffee Es ist außerhalb dieser Datei nicht verfügbar, sodass onsubmit nicht darauf zugreifen kann. Dies verhindert, dass eine andere JavaScript-Datei neu definiert wird bestätigen , ist aber hier nicht sehr hilfreich.

Um die Funktion global zu machen, ändern wir einfach die Zuordnung:

window.validate = (form) ->

Dies hängt an bestätigen zum Fenster Objekt, wodurch es global verfügbar wird. Nochmals kompilieren:

coffee -c form.coffee

dann neu laden, Formular senden und ... keine Übermittlung! Das Kompilieren bei jeder Änderung wird mühsam. Verwenden Sie stattdessen die Funktion 'Überwachen':

coffee -cw *.coffee

-im Startet den Compiler, lässt ihn laufen und kompiliert alle geänderten Dateien, die mit dem übereinstimmen *.Kaffee Muster. Mit dieser Ausführung können wir unsere CoffeeScript-Dateien bearbeiten, die kompilierte Version fast sofort im Browser speichern und neu laden.

Ein-Fenster-Entwicklung: Coda eignet sich hervorragend für die Entwicklung von CoffeeScript - das Terminal kann einfach im Hintergrund summen und für den Browser kompilieren

Ein-Fenster-Entwicklung: Coda eignet sich hervorragend für die Entwicklung von CoffeeScript - das Terminal kann einfach im Hintergrund summen und für den Browser kompilieren

Bohnen mahlen

Wir haben eine Liste der erforderlichen Feldnamen und einen Submit-Handler, um diese zu überprüfen. Um alle Felder mit den angegebenen Namen abzurufen, gehen Sie in JS wie folgt vor:

var required_fields = []; for ( var name in required_field_names ) { var field = form.elements[name]; required_fields.push(field); }

Wir könnten in CoffeeScript transliterieren: Klammern verlieren, Einrückung verwenden. Wir können auch Klammern um Argumente verlieren, die ebenfalls an Funktionen übergeben werden, genau wie in Ruby.

required_fields = [] for name in required_field_names field = form.elements[name] required_fields.push field

Wir können es besser machen:

required_fields = for name in required_field_names return form.elements[name]

Mit anderen Worten, for () gibt ein Array zurück, das die Rückgabewerte jeder Iteration enthält. Denken Sie daran, dass wir in CoffeeScript keine explizite Rückgabe benötigen.

required_fields = for name in required_field_names form.elements[name]

Der for-Block ist jetzt nur noch eine einzelne Anweisung, und CoffeeScript gibt uns den folgenden Trick, bei dem die Bedingung nach der Anweisung gesetzt wird, die wir ausführen möchten:

required_fields = ( form.elements[name] for name in required_field_names )

Das liest sich wie ein Satz:

> Required Fields are the form elements for each name in Required Field Names

Wir haben fünf Zeilen JavaScript zu einer einzigen, sauberen Codezeile zusammengefasst, die genau ausdrückt, was sie tut. validate selbst ist jetzt vier Zeilen lang. Das kompilierte JavaScript enthält rund 18 Zeilen kugelsicheren, engen und speichereffizienten Codes. An CoffeeScript gibt es viel zu mögen.

Schlicht und einfach: hier

Schlicht und einfach: Hier ist unser endgültiger Quellcode (links). Es ist lesbarer Code, was bedeutet, dass es wartbarer Code ist

Den Braten überprüfen

Wir haben ein Array von Eingabeelementen. Überprüfen wir also, ob jedes einen Wert hat. In JavaScript könnten wir dies tun:

var errors = []; for ( var field in required_fields ) { if ( field.value == '' ) { errors.push(field.name); } }

Dies würde eine Reihe von falschen Feldnamen sammeln. Lassen Sie uns das aufräumen:

errors = [] for field in required_fields if field.value == '' errors.push field_name

Dies scheint keine große Ersparnis zu sein. Beachten Sie, dass der if-Block nur eine einzige Anweisung enthält. Dies bedeutet, dass wir den gleichen Trick ausführen können, den wir mit dem for-Block verwaltet haben - indem wir die bedingte Anweisung vor die Bedingung stellen:

errors = [] for field in required_fields errors.push field_name if field.value == ''

Wir könnten den Trick sogar wiederholen und alles in eine einzige Zeile verschieben:

errors = [] (errors.push field_name if field.value == '') for field in required_fields

Warten. Klammern? Die Klammern stellen den Vorrang sicher und markieren einen Punkt: In CoffeeScript sind Klammern optional und nicht gesperrt. CoffeeScript zielt darauf ab, die Lesbarkeit von JavaScript zu verbessern. Wenn also die Verwendung von Klammern dabei hilft, können Sie loslegen.

wie man ein besserer Designer ist

Unsere Validierungsfunktion jetzt:

window.validate = (form) -> required_field_names = ['name','email'] errors = [] required_fields = (form.elements[name] for name in required_field_names) (errors.push field.name if field.value == '') for field in required_fields false

Es bleiben noch zwei Dinge zu tun: Verhindern Sie, dass das Formular nur gesendet wird, wenn Fehler vorliegen, und melden Sie diese Fehler dem Benutzer.

Bracket-Bonus: Eine lesbare Zeile CoffeeScript ist fünf Zeilen obskures JavaScript wert. Wenn die Verwendung von Klammern dabei hilft, dann gehen sie hinein

Bracket-Bonus: Eine lesbare Zeile CoffeeScript ist fünf Zeilen obskures JavaScript wert. Wenn die Verwendung von Klammern dabei hilft, dann gehen sie hinein

Die perfekte Tasse servieren

Das Verhindern der Übermittlung bei Fehlern ist jetzt trivial. Ersetzen Sie die letzte Zeile durch eine Überprüfung der Anzahl der Fehler:

window.validate = (form) -> ... errors.length == 0

bestätigen gibt jetzt explizit die Ja / Nein-Antwort auf: Gibt es keine Fehler im Formular? Dies ist sehr gut lesbar und wartbar: Die letzte Zeile der Funktion fasst genau zusammen, was die Funktion tut. Die Fehlerberichterstattung könnte ähnlich einfach sein und vor der letzten Zeile Folgendes hinzufügen:

alert errors.join(', ') if errors.length > 0

Dies ist jedoch zu einfach: Keine Beschreibungen, nur eine Liste von Feldnamen. Lassen Sie uns dies in eine Fehlerbehandlungsfunktion aufteilen. Bericht . Ersetzen Sie das oben Gesagte durch:

report errors

Fügen Sie dann Folgendes hinzu bestätigen ::

report = (errors) -> alert 'This form has errors: - ' + errors.join(' - ') if errors.length > 0

Unser endgültiger Quellcode sieht folgendermaßen aus:

window.validate = (form) -> required_field_names = ['name','email'] required_fields = (form.elements[name] for name in required_field_names) errors = [] (errors.push field.name if field.value == '') for field in required_fields report errors errors.length == 0 report = (errors) -> alert 'This form has errors: - ' + errors.join(' - ') if errors.length > 0

Aufräumen

Diese Art des schnellen Refactorings war in JavaScript schon immer ein Problem. Das Erstellen von Funktionen kann zu Problemen mit dem Umfang führen, und die syntaktische Suppe verhindert, dass Refactoring die Lesbarkeit des Codes verbessert. Mit CoffeeScript ist das Herausziehen von Funktionen wie der Fehlerbehandlung trivial und trägt lediglich zur besseren Lesbarkeit bei. Wir könnten dies fortsetzen, um die Validierung weiter zu bereinigen:

window.validate = (form) -> errors = get_errors form, ['name','email'] report errors errors.length == 0 get_errors = (form, field_names) -> errors = [] required_fields = (form.elements[name] for name in field_names) (errors.push field.name if field.value == '') for field in required_fields errors report = (errors) -> alert 'This form has errors: - ' + errors.join(' - ') if errors.length > 0

Dreizehn Zeilen sauberen, lesbaren Codes im Vergleich zu 35 Zeilen effizientem, aber ziemlich unlesbarem JavaScript? Das ist ein Weckruf.