Avansert bruk av CoffeeScript

Innholdsfortegnelse
I tidligere opplæringsprogrammer jobbet vi med klasser, og dermed gjorde applikasjonen vår mer modulær, vi så til og med i dybden hvordan vi utførte asynkront arbeid med CoffeeScript som et språk, og gir oss dermed et større utvalg av alternativer for å jobbe med det.
Etter å ha mestret disse konseptene, er det på tide å gå et skritt videre, og bruke det vi vet til å skrive renere, mer funksjonell og selvfølgelig kraftigere kode. Det er på tide å lære å bli strømbrukere av CoffeeScript.
Nå som vi vet hvordan vi skal bruke klasser i applikasjonen vår, er det bare et spørsmål om tid før vi får problemer med den. kontekst. Når vi har enkle funksjoner er det ganske enkelt å se hvilke data denne funksjonen har i sitt omfang, den kjenner globale variabler, variabler definert i funksjonen og en hvilken som helst variabel som ble definert i det lokale omfanget da funksjonen ble opprettet.
Men når metodene er bundet til objekter, blir dette litt mer komplisert. For å illustrere dette, la oss se et eksempel der vi kan se dette problemet, og så får vi se hvordan CoffeeScript kan hjelpe oss:
 klasse Skipsløfteranker: (doneCallback) -> console.log "Løfteanker." setVel: (speed) -> console.log "Setting speed to # {speed}" set seil: -> @levantarAncla @ fixVel 70
Anta at vi i henhold til koden vår ønsker å seile umiddelbart, for dette gjør vi følgende for å påkalle vår funksjon:
 bot = ny Barco bot.zarpar ()
Hvis vi ser nøye ut og overfører denne koden til den virkelige verden, kan vi innse at løfting av ankeret ikke skjer umiddelbart, vi må vente på at ankeret er fullt hevet for å kunne seile. Vi kan løse dette problemet ved å legge til en Ring tilbake og spør om den ble fullført, så vi får vite hvor lang tid denne handlingen tar og vil kalle vår funksjon når den er ferdig, la oss se:
 liftAnchor: (doneCallback) -> console.log "Løfte anker." hvis gjort Ring tilbake? setTimeout doneCallback, 1000
Som vi kan se, påkaller vi bare tilbakeringing hvis den eksisterer, på denne måten sørger vi for at denne prosessen er fullført, og derfor må vi endre vår funksjon sette seil:
 sette seil: -> @levantarAncla -> @ fixVel 70
Det vi gjør er å påkalle funksjonen sette seil Etter at ankeret er løftet, sikrer dette at vi ikke beveger oss før ankeret er helt hevet. Dette ser ganske bra ut, vi skal kompilere koden vår, og vi kommer til å inkludere den genererte .js -filen i en HTML for å se svaret etter konsoll:

Som vi ser på bildet har vi fått en feil der det står at funksjonen ikke eksisterer. Hva skjedde? Det er veldig enkelt, JavaScript har satt verdien Este på måten funksjonen har blitt påkalt, siden da du ringte bot.zarpar verdien Este er knyttet til objektet bot, så dette er bundet til den globale konteksten, og dette er ikke det vi ønsker.
Det vi ønsker å gjøre er å sørge for det Este er alltid knyttet til forekomsten av bot inne i tilbakeringingen, og vi har lykke til siden CoffeeScript den har en funksjonalitet for den saken. For dette vil vi erklære funksjonen med fett pil eller tykk pil, på denne måten vil funksjonen ha Este knyttet til konteksten der den ble erklært, la oss se hvordan koden vår ser ut med denne endringen:
 klasse Skipsløfteranker: (doneCallback) -> console.log "Løfteanker." hvis gjort Ring tilbake? setTimeout doneCallback, 1000 setVel: (speed) -> console.log "Setting speed to # {speed}" set sail: -> @levantarAncla => @fixVel 70 bot = new Barco bot.zarpar ()
La oss kompilere filen vår og se hvordan CoffeeScript Prestasjonsbind med tykk pilfunksjonalitet:

Hva det gjør CoffeeScript før du erklærer Ring tilbake er å angi en lokal variabel _Este, som refererer til Este, siden selv om Ring tilbake er dynamisk bundet til verdien, laster fremdeles den lokale konteksten den ble erklært i. Til slutt skal vi utføre vår genererte fil og deretter se hvordan feilen ble løst:

Etter å ha sett hvordan du løser kontekstproblemet i applikasjonene våre med CoffeeScript Vi kommer til å se en ganske enkel, men kraftig teknikk for å hjelpe oss med å spare arbeid. Det er ikke en avansert teknikk, men det er en logisk måte å gjøre en forbedring av koden vår uten store anstrengelser fra vår side.
MemoiseringHva teknikken til notering er å lagre verdier for en funksjon i stedet for å beregne dem på nytt hver gang funksjonen kalles. Nå som vi vet hvordan vi skal bruke klasser og objekter, kan vi bruke denne kunnskapen til å bruke dem innenfor CoffeeScript og bruk den aktuelle teknikken.
Det er mange måter å utføre prosessen på notering, for denne opplæringen, vil vi holde ting enkelt. For dette er det vi vil gjøre at når visse opplysninger blir forespurt, vil vi bekrefte om den er lagret, i så fall returnere vi den umiddelbart, ellers kan vi beregne den og lagre den for fremtidig bruk. Denne teknikken er ekstremt nyttig når vi trenger å bruke en kompleks algoritme for å motta et svar eller i tilfelle vi bruker et tregt nettverk for å skaffe informasjon.
Så la oss se på koden for å illustrere denne teknikken:
 class Rocket getPath: -> @path? = @doMathComplexProcess ()
For bedre å forklare denne delen av koden skal vi kompilere den for å se hvordan CoffeeScript bygge JavaScript at teknikken vår må spare oss for arbeid i utviklingen, la oss se hvordan koden vår ser ut:

FORSTØRRE

Som vi kan se i koden vår, vil beregningen av banen bare bli utført første gang be om og den lagrede verdien vil bli brukt fra nå av. Vi kunne også se i koden vår CoffeeScript at vi hadde hjelp av den tertiære operatøren ?= som vil evaluere uttrykket i tilfelle at banen er null, i tillegg vil vi ha hjelp fra den implisitte avkastningen av funksjonene som vil returnere resultatet av uttrykket, i dette tilfellet verdien av @trajectory om den har blitt lagret tidligere eller nettopp er beregnet.
Men dette er ikke alt vi kan gjøre med vår nye teknikk CoffeeScript, vi kan til og med lagre mer enn én verdi ved hjelp av en datastruktur, la oss se hvordan vi kan gjøre det:
 klasse SecurityGateway hasAccess: (vakt) -> @access? = {} @access [guard.plate_number]? = verifyCredentials guard.plate_number
Hva denne delen av koden gjør er at i objektet vårt blir resultatet lagret for hver vakt som har bedt om tilgang, vi trenger bare noe unikt for å kunne identifisere dem i objektet vårt, så vi bruker tallerkennummeret for denne oppgaven, la oss se hvordan koden vår blir oversatt når vi kompilerer den:

FORSTØRRE

Det er viktig å nevne at denne teknikken bare skal brukes med informasjon som ikke vil endres under utførelsen av programmet vårt, i tilfelle det er det, anbefaler vi å implementere en løsning basert på cache.
Til slutt vil vi se en måte å overføre alternativer til en funksjon, dette er ikke en spesiell funksjonalitet for CoffeeScriptDet er mer en konvensjon som bruker mange av egenskapene til språket, bruker dem i et mønster som er lett å forstå og som er like nyttig i mange situasjoner som kan oppstå.
Hvordan virker det?Ideen bak dette er enkel, det er å ha en funksjon som godtar dette alternativer objekt som kan inneholde assosiative nøkler for argumentene til den funksjonen. Dette gjør alternativene enkle å forstå fra koden de blir kalt i, fordi det er krøllete seler for å identifisere hva hver verdi gjør. Dette reduserer også bryet med å holde øye med argumentene så vel som deres rekkefølge, siden objektnøklene ikke er avhengige av dette og kan utelates hvis det ikke er nødvendig.
For å implementere alternativer objekter først skal vi bruke valgfrie argumenter som standard til et tomt argument. På denne måten, når vi ringer, kan vi utelate alternativene i tilfelle at verdiene ikke er nødvendige:
 launchNave = (navn, alternativer = {}) -> gå tilbake hvis alternativer. drift dry take take ()
Nå skal vi bruke den tertiære operatøren ?= for å fylle ut verdiene til alternativene som vi vil ha en spesiell standardverdi:
 launchNave = (navn, alternativer = {}) -> options.count? = 10 console.log "# {i} …" for i i [options.count … 0] retur hvis options.drift tørr start ()
Vi definerer en siste verdi, og vi bruker operatøren ? i tilfelle den brukes på ett sted:
 launchSave = (navn, alternativer = {}) -> checkFuel (options.waitComb? 100) options.count? = 10 console.log "# {i} …" for i i [options.count … 0] returner hvis alternativer. tørr start ()
Til slutt drar vi fordel av den tillatte syntaksen til CoffeeScript å sende alternativene til vår funksjon uten parentesene, noe som gir oss en ganske enkel og naturlig samtale:
 launchShip "Millennium Falcon", DryGear: true, nedtelling: 15
For å fullføre skal vi kompilere filen vår og se utdataene fra koden vår JavaScript:

FORSTØRRE

Med sistnevnte avsluttet vi denne opplæringen, hvor vi ikke bare kunne lære avanserte måter å bruke CoffeeScript men heller teknikker som vil hjelpe oss med å skrive bedre kode, at vi med konstant bruk og forskning kan bli bedre utviklere som bruker beste praksis for å utvikle applikasjoner.
wave wave wave wave wave