Avancerad användning av CoffeeScript

Innehållsförteckning
I tidigare handledningar arbetade vi med klasser, vilket gjorde vår applikation mer modulär, vi såg till och med på djupet hur vi utför asynkron arbete med CoffeeScript som ett språk, vilket ger oss ett större utbud av alternativ att arbeta med det.
Efter att ha behärskat dessa begrepp är det dags att gå ett steg längre och använda det vi vet för att skriva renare, mer funktionell och naturligtvis mer kraftfull kod. Det är dags att lära sig att bli kraftanvändare av CoffeeScript.
Nu när vi vet hur vi använder klasser i vår applikation är det bara en tidsfråga innan vi stöter på problem med det. sammanhang. När vi har enkla funktioner är det ganska lätt att se vilka data denna funktion har i sitt omfång, den känner till globala variabler, variabler definierade inom funktionen och alla variabler som definierades i det lokala omfånget när funktionen skapades.
Men när metoderna är bundna till objekt blir det lite mer komplicerat. För att illustrera detta, låt oss se ett exempel där vi kan se detta problem och sedan får vi se hur CoffeeScript kan hjälpa oss:
 klass Skeppslyftankare: (doneCallback) -> console.log "Lyftankare." setVel: (speed) -> console.log "Ställer in hastigheten till # {speed}" sätter segel: -> @levantarAncla @ fixVel 70
Antag då enligt vår kod att vi vill segla omedelbart, för detta gör vi följande för att åberopa vår funktion:
 bot = ny Barco bot.zarpar ()
Om vi ​​tittar noga och överför den här koden till den verkliga världen kan vi inse att lyft av ankaret inte sker omedelbart, vi måste vänta på att ankaret ska vara helt upphöjt för att kunna segla. Vi kan lösa detta problem genom att lägga till en ring tillbaka och frågar om den är klar, så vi vet hur lång tid denna åtgärd tar och kommer att kalla vår funktion när den är klar, låt oss se:
 liftAnchor: (doneCallback) -> console.log "Lyftankare." om gjortCallback? setTimeout doneCallback, 1000
Som vi kan se, åberopar vi bara återuppringning om den finns, på detta sätt ser vi till att processen är slutförd och därför måste vi ändra vår funktion sätta segel:
 segla: -> @levantarAncla -> @ fixVel 70
Vad vi nu gör är att åberopa funktionen sätta segel Efter att ha lyft ankaret säkerställer detta att vi inte kommer att röra oss förrän ankaret är helt lyft. Det här ser ganska bra ut, vi kommer att sammanställa vår kod och vi kommer att inkludera den genererade .js -filen i en HTML för att se svaret per konsol:

Som vi ser på bilden har vi fått ett fel där det står att funktionen inte finns. Vad hände? Det är väldigt enkelt, JavaScript har ställt in värdet Este på det sätt på vilket funktionen har åberopats, sedan när du ringde bot.zarpar värdet Este är kopplad till objektet bot, så detta är bundet till det globala sammanhanget och det är inte det vi vill ha.
Det vi vill göra är att se till att Este är alltid kopplad till förekomsten av bot inuti återuppringningens kropp och vi har tur CoffeeScript det har en funktionalitet för det fallet. För detta kommer vi att deklarera funktionen med fet pil eller tjock pil, på detta sätt kommer funktionen att ha Este kopplat till det sammanhang där det deklarerades, låt oss se hur vår kod ser ut med den här ändringen:
 klass Skeppslyftankare: (doneCallback) -> console.log "Lyftankare." om gjortCallback? setTimeout doneCallback, 1000 setVel: (speed) -> console.log "Ställer in hastigheten till # {speed}" sätter segel: -> @levantarAncla => @fixVel 70 bot = new Barco bot.zarpar ()
Låt oss sammanställa vår fil och se hur CoffeeScript Prestationsbindning med tjock pilfunktion:

Vad den gör CoffeeScript innan deklarerar ring tillbaka är att ställa in en lokal variabel _Est, som hänvisar till Este, eftersom även om ring tillbaka är dynamiskt bunden till värdet laddar fortfarande den lokala kontext där det deklarerades. Slutligen kommer vi att köra vår genererade fil och sedan se hur felet löstes:

Har redan sett hur man löser kontextproblemet i våra applikationer med CoffeeScript Vi kommer att se en ganska enkel men kraftfull teknik för att hjälpa oss att spara arbete. Det är inte en avancerad teknik men det är ett logiskt sätt att göra en förbättring av vår kod utan mycket ansträngning från vår sida.
MemoiseringVad tekniken för memoisering är att lagra värden för en funktion istället för att beräkna dem varje gång funktionen anropas. Nu när vi vet hur vi använder klasser och objekt kan vi använda denna kunskap för att tillämpa dem inom CoffeeScript och använd den aktuella tekniken.
Det finns många sätt att utföra processen memoisering, för fallet med denna handledning kommer vi att hålla saker enkla. För detta, vad vi kommer att göra är att när viss information begärs kommer vi att verifiera om den lagras, i så fall returnerar vi den omedelbart, annars kan vi beräkna den och spara den för framtida bruk. Denna teknik är extremt användbar när vi behöver använda en komplex algoritm för att ta emot ett svar eller om vi använder ett långsamt nätverk för att få information.
Så låt oss titta på koden för att illustrera denna teknik:
 class Rocket getPath: -> @path? = @doMathComplexProcess ()
För att bättre förklara denna del av koden kommer vi att sammanställa den för att se hur CoffeeScript bygga JavaScript att vår teknik måste spara oss arbete i vår utveckling, låt oss se hur vår kod ser ut:

FÖRSTORA

Som vi kan se i vår kod kommer beräkningen av banan endast att utföras första gången begäran och det lagrade värdet kommer att användas från och med nu. Vi kunde också se i vår kod CoffeeScript att vi hade hjälp av tertiäroperatören ?= som kommer att utvärdera uttrycket i det fall att sökvägen är noll, dessutom kommer vi att ha hjälp från den implicita avkastningen av funktionerna som kommer att returnera resultatet av uttrycket, i detta fall värdet av @bana om det har lagrats tidigare eller just har beräknats.
Men det är inte allt vi kan göra med vår nya teknik CoffeeScript, vi kan till och med lagra mer än ett värde med hjälp av en datastruktur, låt oss se hur vi kan göra det:
 klass SecurityGateway hasAccess: (guard) -> @access? = {} @access [guard.plate_number]? = verifyCredentials guard.plate_number
Vad denna del av koden gör är att i vårt objekt lagras resultatet för varje vakt som har begärt åtkomst, vi skulle bara behöva något unikt för att kunna identifiera dem i vårt objekt så vi använder plattnumret för den här uppgif.webpten, låt oss se hur vår kod översätts när vi sammanställer den:

FÖRSTORA

Det är viktigt att nämna att denna teknik endast bör användas med information som inte kommer att förändras under genomförandet av vårt program, i det fall det är så rekommenderar vi att implementera en lösning baserad på cache.
Slutligen kommer vi att se ett sätt att skicka alternativ till en funktion, detta är inte en speciell funktionalitet för CoffeeScriptDet är mer en konvention som använder många av språkets egenskaper, använder dem i ett mönster som är lätt att förstå och som är lika användbart i många situationer som kan uppstå.
Hur fungerar det?Tanken bakom detta är enkel, det är att ha en funktion som accepterar detta alternativ objekt som kan innehålla associerade nycklar för den funktionens argument. Detta gör alternativen lätta att förstå från koden där de kallas eftersom det finns lockiga hängslen för att identifiera vad varje värde gör. Detta minskar också besväret med att hålla ett öga på argumenten och deras ordning, eftersom objektnycklarna inte är beroende av detta och kan utelämnas om det inte behövs.
För att genomföra alternativobjekt först kommer vi att använda valfria argument som standard till ett tomt argument. På detta sätt, när vi ringer, kan vi utelämna alternativen om värdena inte behövs:
 launchNave = (namn, alternativ = {}) -> retur om alternativ. drift torr start ()
Nu kommer vi att använda den tertiära operatören ?= för att fylla i värdena för alternativen som vi vill ha ett särskilt standardvärde:
 launchNave = (namn, alternativ = {}) -> options.count? = 10 console.log "# {i} …" för i i [options.count … 0] retur om options.drift torrt startar ()
Vi definierar ett sista värde och vi använder operatören ? om det används på ett ställe:
 launchSave = (namn, optioner = {}) -> checkFuel (options.waitComb? 100) options.count? = 10 console.log "# {i} …" för i i [options.count … 0] returnera om alternativ. torr start ()
Slutligen utnyttjar vi den tillåtande syntaxen för CoffeeScript att skicka alternativen till vår funktion utan parenteser, vilket ger oss ett ganska enkelt och naturligt samtal:
 launchShip "Millennium Falcon", DryGear: true, nedräkning: 15
För att avsluta kommer vi att kompilera vår fil och se utmatningen av vår kod i JavaScript:

FÖRSTORA

Med det senare avslutade vi denna handledning, där vi inte bara kunde lära oss avancerade sätt att använda CoffeeScript utan snarare tekniker som hjälper oss att skriva bättre kod, att vi med ständig användning och forskning kan bli bättre utvecklare som använder de bästa metoderna för att utveckla applikationer.
wave wave wave wave wave