Înfășurarea funcțiilor JavaScript vă permite să adăugați logică comună la funcțiile pe care nu le controlați, cum ar fi funcțiile native și externe. Multe biblioteci JavaScript, cum ar fi agenții TrackJS, trebuie să înfășoare funcții externe pentru a-și face treaba. Adăugarea de wrappers ne permite să ascultăm telemetria, erorile și jurnalele din codul dumneavoastră, fără a fi nevoie să apelați în mod explicit API-ul nostru.
Poate doriți să înfășurați o funcție pentru a adăuga instrumentare sau logică temporară de depanare. De asemenea, puteți schimba comportamentul unei biblioteci externe fără a fi nevoie să modificați sursa.
Basic Function Wrapping
Pentru că JavaScript este minunat de dinamic, putem înfășura o funcție prin simpla redefinire a funcției cu ceva nou. De exemplu, luați în considerare această înfășurare a funcției myFunction
:
În acest exemplu trivial, am înfășurat funcția originală myFunction
și am adăugat un mesaj de logare. Dar sunt multe lucruri de care nu ne-am ocupat:
- Cum trecem argumentele funcției?
- Cum menținem domeniul de aplicare (valoarea lui
this
)? - Cum obținem valoarea de retur?
- Ce se întâmplă dacă apare o eroare?
Pentru a ne descurca cu aceste lucruri, trebuie să devenim un pic mai isteți în structurarea noastră.
Rețineți că în acest exemplu nu doar invocăm funcția, ci o call
-izolăm cu valoarea pentru this
și argumentele a
, b
și c
. Valoarea lui this
va fi transmisă de oriunde atașați funcția înfășurată, Window
în acest exemplu.
Am înconjurat, de asemenea, întreaga funcție într-un bloc try/catch
, astfel încât să putem invoca o logică personalizată în cazul unei erori, să o respingem din nou sau să returnăm o valoare implicită.
Anveloparea avansată a funcțiilor
Exemplul de bază de înfășurare va funcționa în 90% din cazuri, dar dacă construiți biblioteci partajate, cum ar fi agenții TrackJS, acest lucru nu este suficient de bun! Pentru a ne înfășura funcțiile ca un profesionist, există câteva cazuri limită cu care ar trebui să ne confruntăm:
- Ce facem cu argumentele nedeclarate sau necunoscute?
- Cum potrivim semnătura funcției?
- Cum oglindim proprietățile funcției?
Există 3 modificări subtile, dar importante. În primul rând (#1), am numit funcția. Pare redundant, dar codul de utilizator poate verifica valoarea lui function.name
, așa că este important să menținem numele atunci când înfășurăm.
A doua modificare (#2) este în modul în care am numit funcția înfășurată, folosind apply
în loc de call
. Acest lucru ne permite să trecem prin intermediul unui obiect arguments
, care este un obiect de tip array cu toate argumentele transmise funcției în timpul execuției. Acest lucru ne permite să suportăm funcțiile care pot avea un număr nedefinit sau variabil de argumente.
Cu apply
, nu avem nevoie de argumentele a
, b
și c
definite în semnătura funcției. Dar, continuând să declarăm aceleași argumente ca în funcția originală, menținem aritatea funcției. Adică, Function.length
returnează numărul de argumente definite în semnătură, iar acest lucru va oglindi funcția originală.
Modificarea finală (#3) copiază orice proprietăți specificate de utilizator din funcția originală pe învelișul nostru.
Limitări
Acest înveliș este minuțios, dar întotdeauna există limitări în JavaScript. În mod specific, este dificil să înfășurați corect o funcție cu un prototip non-standard, cum ar fi un constructor de obiecte. Acesta este un caz de utilizare rezolvat mai bine prin moștenire.
În general, schimbarea prototipului unei funcții este posibilă, dar nu este o idee bună. Există implicații serioase asupra performanței și efecte secundare neintenționate în manipularea prototipurilor.
Respectați mediul
Încapsularea funcțiilor vă oferă multă putere pentru a instrumenta și manipula mediul JavaScript. Aveți responsabilitatea de a manevra această putere cu înțelepciune. Dacă construiți wrappere de funcții, asigurați-vă că respectați utilizatorul și mediul în care operați. Este posibil să existe și alte wrappers în vigoare, alți ascultători atașați pentru evenimente și așteptări privind API-urile funcțiilor. Pășiți ușor și nu rupeți codul extern.
.