Cuprins
În tutoriale anterioare, am lucrat cu cursurile, făcând astfel aplicația noastră mai modulară, chiar am văzut în profunzime cum să efectuăm lucrări asincrone folosind CoffeeScript ca limbă, oferindu-ne astfel o gamă mai largă de opțiuni pentru a lucra cu ea.După ce am însușit aceste concepte, este timpul să facem un pas mai departe și să folosim ceea ce știm pentru a scrie un cod mai curat, mai funcțional și, desigur, mai puternic. Este timpul să învățăm cum să devenim utilizatori puternici ai CoffeeScript.
Acum, că știm cum să folosim cursurile în aplicația noastră, este doar o chestiune de timp înainte să avem probleme cu aceasta. context. Când avem funcții simple, este destul de ușor să vedem ce date are această funcție în sfera sa, cunoaște variabile globale, variabile definite în cadrul funcției și orice variabilă care a fost definită în sfera locală atunci când funcția a fost creată.
Dar când metodele sunt legate de obiecte, acest lucru devine puțin mai complicat. Pentru a ilustra acest lucru, să vedem un exemplu în care putem vedea această problemă și apoi vom vedea cum CoffeeScript ne poate ajuta:
clasa Ancoră de ridicare a navei: (doneCallback) -> console.log "Ancoră de ridicare." setVel: (speed) -> console.log "Setarea vitezei la # {speed}" set sail: -> @levantarAncla @ fixVel 70Să presupunem că, conform codului nostru, vrem să pornim imediat, pentru aceasta facem următoarele pentru a invoca funcția noastră:
bot = nou Barco bot.zarpar ()Dacă privim cu atenție și transferăm acest cod în lumea reală, ne putem da seama că ridicarea ancorei nu se întâmplă imediat, trebuie să așteptăm ca ancora să fie ridicată complet pentru a putea naviga. Putem rezolva această problemă adăugând un sună din nou și întrebând dacă a fost finalizată, așa că vom ști cât durează această acțiune și ne vom apela funcția odată terminată, să vedem:
liftAnchor: (doneCallback) -> console.log "Ancora de ridicare". dacă ați făcut apel? setTimeout done Callback, 1000După cum putem vedea, invocăm callback-ul doar dacă acesta există, în acest fel ne asigurăm că acest proces este finalizat și, prin urmare, trebuie să ne modificăm funcția a navigat:
salvați: -> @levantarAncla -> @ fixVel 70Acum ceea ce facem este să invocăm funcția a navigat După ridicarea ancorei, acest lucru ne asigură că nu ne vom mișca până când ancora nu este ridicată complet. Arată destul de bine, vom compila codul nostru și vom include fișierul .js generat într-un HTML pentru a vedea răspunsul de la consolă:
După cum vedem în imagine, am obținut o eroare în care se spune că funcția nu există. Ce s-a întâmplat? Este foarte simplu, JavaScript a setat valoarea Este în modul în care funcția a fost invocată, de la momentul apelării bot.zarpar valoarea Este este legat de obiect bot, deci acest lucru este legat de contextul global și nu asta ne dorim.
Ceea ce vrem să facem este să ne asigurăm că Este este întotdeauna legat de instanța de bot în interiorul corpului callback-ului și suntem norocoși, de vreme ce CoffeeScript are o funcționalitate pentru cazul respectiv. Pentru aceasta vom declara funcția cu săgeată grasă sau săgeată groasă, în acest fel funcția va avea Este legat de contextul în care a fost declarat, să vedem cum arată codul nostru cu această modificare:
clasa Ancoră de ridicare a navei: (doneCallback) -> console.log "Ancoră de ridicare." dacă ați făcut apel? setTimeout doneCallback, 1000 setVel: (speed) -> console.log "Setting speed to # {speed}" set sail: -> @levantarAncla => @fixVel 70 bot = new Barco bot.zarpar ()Să ne compilăm fișierul și să vedem cum CoffeeScript Realizarea legăturilor cu funcționalitatea săgeții groase:
Ce face CoffeeScript înainte de a declara sună din nou este de a seta o variabilă locală _Este, care se referă la Este, deoarece chiar dacă sună din nou este legat dinamic de valoarea încarcă încă contextul local în care a fost declarat. În cele din urmă, vom executa fișierul generat și vom vedea cum a fost rezolvată eroarea:
După ce am văzut deja cum să rezolvăm problema contextului din aplicațiile noastre cu CoffeeScript Vom vedea o tehnică destul de simplă, dar puternică, care să ne ajute să economisim muncă. Nu este o tehnică avansată, dar este o modalitate logică de a face o îmbunătățire a codului nostru fără eforturi mari din partea noastră.
MemorizareCare este tehnica memoizare este să stochezi valorile unei funcții în loc să le recalculezi de fiecare dată când este apelată funcția. Acum, că știm să folosim clase și obiecte, putem folosi aceste cunoștințe pentru a le aplica în interior CoffeeScript și utilizați tehnica în cauză.
Există multe modalități de a efectua procesul de memoizare, pentru cazul acestui tutorial vom păstra lucrurile simple. Pentru aceasta, ceea ce vom face este că, atunci când sunt solicitate anumite informații, vom verifica dacă sunt stocate, dacă da, le returnăm imediat, altfel o putem calcula și salva pentru o utilizare ulterioară. Această tehnică este extrem de utilă atunci când trebuie să folosim un algoritm complex pentru a primi un răspuns sau în cazul în care folosim o rețea lentă pentru a obține informații.
Deci, să ne uităm la cod pentru a ilustra această tehnică:
clasa Rocket getPath: -> @path? = @doMathComplexProcess ()Pentru a explica mai bine această porțiune de cod, o vom compila pentru a vedea cum CoffeeScript construiți JavaScript că tehnica noastră va trebui să ne salveze munca în dezvoltarea noastră, să vedem cum arată codul nostru:
MARI
După cum putem vedea în codul nostru, calculul traiectoriei va fi efectuat numai pentru prima dată cerere iar valoarea stocată va fi utilizată de acum înainte. Am putea vedea și în codul nostru CoffeeScript că am avut ajutorul operatorului terțiar ?= care va evalua expresia în cazul în care calea este nulă, în plus vom avea ajutor de la returnarea implicită a funcțiilor care vor returna rezultatul expresiei, în acest caz valoarea @traiectorie dacă a fost stocat anterior sau tocmai a fost calculat.Dar asta nu este tot ce putem face cu noua noastră tehnică CoffeeScript, putem chiar stoca mai multe valori folosind o structură de date, să vedem cum o putem face:
class SecurityGateway hasAccess: (guard) -> @access? = {} @access [guard.plate_number]? = verifyCredentials guard.plate_numberCeea ce face această porțiune de cod este că în obiectul nostru rezultatul este stocat pentru fiecare pază care a solicitat accesul, am avea nevoie doar de ceva unic pentru a le putea identifica în obiectul nostru, astfel încât să folosim numărul plăcii pentru această sarcină, să vedem cum este tradus codul nostru atunci când îl compilăm:
MARI
Este important de menționat că această tehnică trebuie utilizată numai cu informații care nu se vor schimba în timpul executării programului nostru, în cazul în care este, recomandăm implementarea unei soluții bazate pe cache.În cele din urmă vom vedea o modalitate de a transmite opțiuni unei funcții, aceasta nu este o funcționalitate specială a CoffeeScriptEste mai mult o convenție care folosește multe dintre caracteristicile limbii, folosindu-le într-un model ușor de înțeles și care este la fel de util în multe situații care pot apărea.
Cum functioneazã?Ideea din spatele acestui lucru este simplă, este să ai o funcție care acceptă acest lucru obiect opțiuni care poate conține chei asociative pentru argumentele funcției respective. Acest lucru face ca opțiunile să fie ușor de înțeles din codul în care sunt apelate, deoarece există acolade pentru a identifica ce face fiecare valoare. Acest lucru reduce, de asemenea, hassle de a urmări argumentele, precum și ordinea lor, deoarece cheile obiect nu sunt dependente de acest lucru și pot fi omise dacă nu sunt necesare.
Pentru a implementa obiecte opțiuni mai întâi vom folosi argumente opționale pentru a seta implicit un argument gol. În acest fel, atunci când efectuăm apelul, putem omite opțiunile în cazul în care valorile nu sunt necesare:
launchNave = (nume, opțiuni = {}) -> întoarcere dacă options.drift dry take off ()Acum vom folosi operatorul terțiar ?= pentru a completa valorile opțiunilor pe care dorim să le avem o valoare implicită specială:
launchNave = (nume, opțiuni = {}) -> options.count? = 10 console.log "# {i} …" pentru i în [options.count … 0] returnează dacă options.drift dry take off ()Definim o ultimă valoare și folosim operatorul ? în cazul în care este utilizat într-un singur loc:
launchSave = (name, options = {}) -> checkFuel (options.waitComb? 100) options.count? = 10 console.log "# {i} …" pentru i în [options.count … 0] returnează dacă opțiuni. uscat decola ()În cele din urmă, profităm de sintaxa permisivă a CoffeeScript pentru a trimite opțiunile la funcția noastră fără paranteze, oferindu-ne un apel destul de simplu și natural:
launchShip "Millennium Falcon", DryGear: adevărat, numărătoare inversă: 15Pentru a termina, vom compila fișierul nostru și vom vedea rezultatul codului nostru în JavaScript:
MARI
Cu acesta din urmă am terminat acest tutorial, unde am putut învăța nu numai modalități avansate de utilizare CoffeeScript ci mai degrabă tehnici care ne vor ajuta să scriem un cod mai bun, că, folosind și cercetând constant, putem deveni dezvoltatori mai buni care folosesc cele mai bune practici pentru dezvoltarea aplicațiilor.