Innhold
Denne artikkelen dukket først opp i nummer 221 av .net magazine - verdens mest solgte magasin for webdesignere og utviklere.
JavaScript er ikke veldig lesbart, og uleselig kode er vanskelig å vedlikeholde. Sammenlignet med Ruby eller Python er det parenteser, seler og sitater overalt. Ofte er det mer syntaks enn programvare.
Skriv inn CoffeeScript. Det er ikke et rammeverk, men kompilerer i stedet for kjørbart JavaScript. Du skriver CoffeeScript, kompilerer det, og dukker opp ren, tett JavaScript klar for nettleseren. Du får optimalisert JavaScript, men jobber med ren, forståelig, vedlikeholdbar kode.
CoffeeScript begynner å være veldig fornuftig når du har skrevet noe, så la oss gå i gang. Først skal vi installere CoffeeScript-kompilatoren og konvertere CoffeeScript-filene til JavaScript som vi kan laste inn i nettleseren vår.
For å få CoffeeScript installert på utviklingsmaskinen din, trenger du et * nix-lignende miljø, et tekstredigeringsprogram, en terminal og en nettleser for å sjekke resultatene. Først installerer vi node.js (en JavaScript-kjøretid som CoffeeScript trenger for å gjøre det magisk). Vi installerer deretter nodens pakkebehandling (npm) og bruker den til å installere CoffeeScript selv. På OS X er den enkleste måten å gjøre dette med hjemmebrygging. Forsikre deg om at du har XCode installert, følg deretter instruksjonene for å installere homebrew, eller bare åpne en terminalsession og skriv:
/ usr / bin / ruby -e "$ (curl -fsSL https://raw.github.com/gist/323731)"Install node.js: bryg installasjonsnode
deretter npm og CoffeeScript:
krølle http://npmjs.org/install.sh | sh npm installer -g kaffe-skript
Hvis du kjører Linux, kan pakkeadministratoren installere node, og deretter installere npm og CoffeeScript. Hvis du derimot bruker Windows, kan du prøve å følge Matthew Podwysockis instruksjoner på CodeBetter. Denne opplæringen handler om CoffeeScript-syntaksen, så la oss holde prosjektmålet enkelt: aktiver validering på klientsiden på et skjema. Her er skjemaet vårt, i index.html:
form id = "contact_form"> ol> li> label> Name / label> input type = "text" name = "name"> / li> li> label> Email / label> input type = "email" name = "email "> / li> li> label> Forespørsel / label> textarea name =" inquiry "> / textarea> / li> / ol> ol> li> input type =" send "> / li> / ol> / form>
Vi har også en katalog, manus, som inneholder en tom fil kalt form.coffee.
Koke vannet
La oss skrive CoffeeScript! Åpne skjema. Kaffe og legg til følgende:
required_field_names = [’name’, ’email’]
Bare JavaScript så langt, men det er en start. La oss kompilere form.coffee. Åpne en terminal og cd i skriptkatalogen:
cd offentlig / skript
CoffeeScripts kaffeverktøy kan kompilere filen:
kaffe -c form.coffee
De -c flagg forteller kaffe om å kompilere CoffeeScript til en fil. Uten den samler og kjører kaffe filen. -c vil skrive JavaScript ut til en fil som heter form.js, i samme katalog som form.coffee fil. La oss se på form.js:
(funksjon () {var required_field_names; required_field_names = [’name’, ’email’];}). ring (dette);
Hva har skjedd? De required_field_names variabel har blitt avgrenset av var, og hele skriptet er pakket inn i et navneområde. Dette beskytter oss mot en av de vanligste kildene til feil i JavaScript: utilsiktede globale variabler. I CoffeeScript er variabler lokale som standard, i stedet for globale som i vanlig JavaScript. Hvis du aldri har bekymret deg for å scope i JavaScript før, er du veldig heldig. Hvis du har det, er dette en livredder.
Den første slurk
La oss inkludere JavaScript i index.html:
head> script src = "/ script / form.js"> / script> / head>
og oppdater skjemaet for å ringe en funksjon når den sendes inn:
form onsubmit = "return validate (this);">
La oss erklære den obligatoriske feltgruppen i denne valideringsfunksjonen og returnere falsk for å forhindre at skjemaet sendes inn under utvikling. I JS kan vi gjøre:
var validate = function (form) {var required_field_names = [’name’, ’email’]; returner falsk; }
Med CoffeeScript kan vi tape var anrop. I tillegg:
funksjon (args) {
blir til:
(args) ->
og i stedet for seler, bruker vi innrykk for å definere funksjonens innhold:
validate = (form) -> required_field_names = [’name’, ’email’] returner false
Legg merke til at vi også har droppet etterfølgende semikolon. Et siste triks: CoffeeScript returnerer resultatet av det siste uttrykket i en funksjon, slik at vi kan miste returen:
validate = (form) -> required_field_names = [’name’, ’email’] false
Kompilere:
kaffe -c form.coffee
og se på form.js å sjekke. Last inn skjemaet vårt, trykk Send og ... skjemaet sender inn. Hva har gått galt?
CoffeeScript oppretter alt i et navneområde og med lokalt omfang. Det betyr at mens validere er tilgjengelig for alt innen form.coffee, den er ikke tilgjengelig utenfor den filen, så onsubmit kan ikke få tilgang til den. Dette forhindrer at en ny JavaScript-fil omdefinerer validere, men er ikke veldig nyttig her.
For å gjøre funksjonen global, endrer vi bare oppgaven:
window.validate = (skjema) ->
Dette fester seg validere til vindu objekt, noe som gjør det globalt tilgjengelig. Kompilere igjen:
kaffe -c form.coffee
last deretter inn på nytt, send inn skjemaet og ... ingen innlevering! Å kompilere for hver endring blir kjedelig, så la oss bruke funksjonen "se" i stedet:
kaffe -cw *. kaffe
-w starter kompilatoren og lar den gå, og kompilerer alle endrede filer som samsvarer med *.kaffe mønster. Når dette kjører, kan vi redigere CoffeeScript-filene våre, lagre og laste inn den kompilerte versjonen i nettleseren nesten umiddelbart.
Maling av bønner
Vi har en liste over obligatoriske feltnavn og en innsendingsbehandler for å sjekke dem. For å hente alle feltene med navnene som er gitt, kan vi gjøre følgende i JS:
var required_fields = []; for (var name in required_field_names) {var field = form.elements [name]; required_fields.push (felt); }
Vi kunne translitterere til CoffeeScript: miste tannregulering, bruk innrykk. Vi kan også miste parenteser rundt argumenter som sendes til funksjoner, akkurat som i Ruby, og gir:
required_fields = [] for navn i required_field_names field = form.elements [name] required_fields.push field
Vi kan gå en bedre:
required_fields = for navn i required_field_names return form.elements [name]
Med andre ord vil for () returnere en matrise som inneholder returverdiene fra hver iterasjon. Husk at vi ikke trenger en eksplisitt retur i CoffeeScript, så:
required_fields = for navn i required_field_names form.elements [navn]
For block er nå bare en enkelt uttalelse, og CoffeeScript gir oss følgende triks, og setter tilstanden etter uttalelsen vi vil kjøre:
required_fields = (form.elements [name] for name in required_field_names)
Dette lyder som en setning:
> Nødvendige felt er skjemaelementene for hvert navn i Nødvendige feltnavn
Vi har destillert fem linjer JavaScript ned til en enkelt, ren linje med kode som uttrykker nøyaktig hva den gjør. validere seg selv er nå fire linjer lang. Det kompilerte JavaScript sitter på rundt 18 linjer med skuddsikker, stram og minneeffektiv kode. Det er mye å like ved CoffeeScript.
Sjekke steken
Vi har en rekke inngangselementer, så la oss sjekke at hver har en verdi. I JavaScript kan vi gjøre dette:
var feil = []; for (var felt i required_fields) {if (field.value == ’’) {error.push (field.name); }}
Dette ville samle en rekke dårlige feltnavn. La oss ordne dette:
feil = [] for felt i obligatoriske felt hvis felt.verdi == ’’ feil. trykk feltnavn
Dette ser ikke ut til å være mye å spare. Legg merke til at det bare er en enkelt uttalelse i if-blokken. Dette betyr at vi kan gjøre det samme trikset som vi klarte med for block - å sette betinget uttalelse foran tilstanden:
feil = [] for felt i required_fields feil. trykk feltnavn hvis field.value == ’’
Vi kan til og med gjenta trikset og flytte alt til en enkelt linje:
feil = [] (error.push field_name if field.value == ’’) for felt i required_fields
Vente. Braketter? Parentesene har forrang og markerer et poeng: i CoffeeScript er parenteser valgfrie, ikke utestengt. CoffeeScript har som mål å forbedre JavaScript-lesbarheten, så hvis bruk av parentes hjelper med det, så er det i gang.
Vår valideringsfunksjon nå:
window.validate = (form) -> required_field_names = ['name', 'email'] feil = [] required_fields = (form.elements [name] for name in required_field_names) (error.push field.name if field.value = = '') for felt i required_fields false
Det er to ting du må gjøre - forhindre at skjemaet bare sendes inn hvis vi har feil og rapporterer disse feilene til brukeren.
Serverer den perfekte koppen
Å forhindre innlevering ved feil er nå trivielt. Erstatt den siste linjen med en sjekk av antall feil:
window.validate = (skjema) -> ... feil.lengde == 0
validere gir nå eksplisitt ja / nei-svaret på: er det null feil på skjemaet? Dette er veldig lesbart og vedlikeholdbart: den endelige linjen i funksjonen oppsummerer nøyaktig hva funksjonen gjør. Feilrapporteringen kan være like enkel og legge til følgende før siste linje:
varslingsfeil. bli med (’,’) hvis feil.lengde> 0
Dette er imidlertid for enkelt: ingen beskrivelser, bare en liste over feltnavn. La oss bryte ut dette til en feilhåndteringsfunksjon, rapportere. Erstatt ovenstående med:
rapporter feil
legg deretter til følgende nedenfor validere:
rapport = (feil) -> varsel "Dette skjemaet har feil: n n-" + feil.forenes (" n-") hvis feil.lengde> 0
Den endelige kildekoden vår ser slik ut:
window.validate = (form) -> required_field_names = ['name', 'email'] required_fields = (form.elements [name] for name in required_field_names) feil = [] (error.push field.name hvis field.value = = '') for felt i obligatoriske felt rapporterer feil feil. lengde == 0 rapport = (feil) -> varsel "Dette skjemaet har feil: n n-" + feil.foren (" n-") hvis feil. lengde> 0
Rydder opp
Denne typen raske refactoring har alltid vært en smerte i JavaScript. Å lage funksjoner kan føre til avgrensingsproblemer, og den syntaktiske suppen forhindrer refactoring fra å legge til lesbarheten til koden. Med CoffeeScript er å trekke ut funksjonalitet som feilhåndtering trivielt og gjør ikke annet enn å lese. Vi kan fortsette dette for å rydde opp i validering ytterligere:
window.validate = (skjema) -> feil = get_errors skjema, ['navn', 'e-post'] rapporter feil feil.lengde == 0 get_errors = (skjema, feltnavn) -> feil = [] required_fields = (form.elements [navn] for navn i feltnavn) (error.push field.name if field.value == '') for felt i required_fields feilrapport = (feil) -> varsel "Dette skjemaet har feil: n n-" + error.join (" n-") hvis feil.lengde> 0
Tretten linjer med ren, lesbar kode, mot 35 linjer med effektiv, men ganske mye uleselig JavaScript? Nå er det en vekker.