Domeniul de aplicare și închiderile

În JavaScript, domeniul de aplicare este contextul în care este executat codul. Există trei tipuri de domeniu de aplicare: domeniul de aplicare global, domeniul de aplicare local (denumit uneori "domeniul de aplicare al funcției") și domeniul de aplicare eval.

Codul definit folosind var în interiorul unei funcții este specifică local și este "vizibilă" doar pentru alte expresii din această funcție, care include codul în interiorul oricărei funcții imbricate / copil. Variabilele definite în domeniul de aplicare global pot fi accesate de oriunde, deoarece acestea reprezintă cel mai înalt nivel și ultima oprire din lanțul de aplicare.

Examinați codul care urmează și asigurați-vă că înțelegeți că fiecare declarație de foo este unic datorită domeniului de aplicare.

Mostră: sample110.html

 

Asigurați-vă că ați înțeles fiecare foo variabila conține o valoare diferită deoarece fiecare este definită într-un domeniu specific delimitat.

Poate fi creat un număr nelimitat de domenii de funcții și eval, în timp ce un mediu global este utilizat de un mediu JavaScript.

Domeniul de aplicare global este ultima oprire din lanțul de aplicare.

Funcțiile care conțin funcții creează domenii de execuție stivuite. Aceste stive, care sunt înlănțuite împreună, sunt adesea denumite lanț de aplicare.


JavaScript nu are un domeniu de aplicare

Deoarece declarațiile logice (dacă) și declarații looping (pentru) nu creează un domeniu de aplicare, variabilele se pot suprascrie reciproc. Examinați următorul cod și asigurați-vă că înțelegeți că valoarea lui foo este redefinit ca programul execută codul.

Mostră: sample111.html

 

Asa de foo se modifică pe măsură ce codul se execută, deoarece JavaScript nu are o funcție de blocare a domeniului, globală sau eval.


Utilizare var În interiorul funcțiilor de declarare a variabilelor și de evitare a scopului Gotchas

JavaScript va declara orice variabile lipsesc a var (chiar și cele conținute într-o funcție sau funcții încapsulate) să se afle în sfera globală de aplicare, în locul scopului local dorit. Aruncați o privire la codul care urmează și observați că fără utilizarea var pentru a declara o bară, variabila este de fapt definită în domeniul de aplicare global și nu domeniul de aplicare local, unde ar trebui să fie.

Mostră: sample112.html

 

Conceptul de a lua aici este că ar trebui să utilizați întotdeauna var când se definesc variabilele din interiorul unei funcții. Acest lucru vă va împiedica să vă ocupați de problemele potențial confuz de aplicare. Excepția la această convenție, desigur, este atunci când doriți să creați sau să modificați proprietăți în domeniul global de aplicare dintr-o funcție.


Lanțul de domeniu (cunoscut și sub numele de Lexical Scooping)

Există un lanț de căutare care este urmat atunci când JavaScript caută valoarea asociată unei variabile. Acest lanț se bazează pe ierarhia domeniului. În codul care urmează, înregistrez valoarea sayHiText de la func2 funcție de domeniu.

Mostră: sample113.html

 

Cum este valoarea lui sayHiText găsită atunci când nu este cuprinsă în interiorul domeniului de aplicare al directivei func2 funcţie? JavaScript prima arata in func2 funcția pentru o variabilă numită sayHiText. Nu găsesc func2 acolo, arata func2funcția parentală, func1. sayHiText variabila nu este găsită în func1 domeniul de aplicare, fie, astfel încât JavaScript apoi continuă până la domeniul de aplicare global în cazul în care sayHiText se găsește, în acest moment valoarea lui sayHiText a fost livrat. Dacă sayHiText nu au fost definite în domeniul global, nedefinit ar fi fost returnat de JavaScript.

Acesta este un concept foarte important de înțeles. Să examinăm un alt exemplu de cod, unul în care luăm trei valori din trei domenii diferite.

Mostră: sample114.html

 

Valoarea pentru z este locală la bar funcția și contextul în care console.log este invocată. Valoarea pentru y este in foo funcția, care este părintele lui bar(), și valoarea pentru X este în domeniul de aplicare global. Toate acestea sunt accesibile bar funcția prin intermediul lanțului de aplicare. Asigurați-vă că înțelegeți că variabilele de referință din bar funcția va verifica până la capăt lanțul de aplicare pentru variabilele la care se face referire.

Lanțul de aplicare, dacă vă gândiți la el, nu este atât de diferit de lanțul prototip. Ambele sunt pur și simplu o modalitate de a căuta o valoare prin verificarea unui set sistematic și ierarhic de locații.


Căutarea lanțului de domeniu returnează prima valoare găsită

În proba de cod care urmează, o variabilă numită X există în același domeniu în care este examinată console.log. Această valoare "locală" X este folosit, și s-ar putea spune că acesta este umbre sau măști, numit identic X variabilele găsite mai sus în lanțul de aplicare.

Mostră: sample115.html

 

Amintiți-vă că domeniul de căutare se termină atunci când variabila se găsește în cea mai apropiată legătură disponibilă a lanțului, chiar dacă aceeași denumire a variabilei este utilizată mai sus în lanț.


Domeniul de aplicare este determinat în timpul definiției funcției, nu este invocarea

Deoarece funcțiile determină domeniul de aplicare și funcțiile pot fi transmise în jurul valorii de orice valoare JavaScript, s-ar putea crede că descifrarea lanțului de aplicare este complicată. Este de fapt foarte simplu. Lanțul de domeniu este decis în funcție de localizarea unei funcții în timpul definiției, nu în timpul invocării. Acesta este, de asemenea, numit lexical scoping. Gândiți-vă lung și greu despre acest lucru, deoarece majoritatea oamenilor se împiedică adesea în codul JavaScript.

Lanțul de sferă de aplicare este creat înainte de a invoca o funcție. Din acest motiv, putem crea închideri. De exemplu, putem avea o funcție de returnare a unei funcții imbricate în domeniul de aplicare global, totuși funcția noastră poate totuși accesa, prin intermediul lanțului de aplicare, domeniul de aplicare al funcției părinte. În exemplul următor, definim a parentFunction care returnează o funcție anonimă și numim funcția returnată din domeniul global. Pentru că funcția noastră anonimă a fost definită ca fiind conținută în interiorul parentFunction, are încă acces la parentFunctions atunci când este invocată. Aceasta se numește închidere.

Mostră: sample116.html

 

Ideea pe care ar trebui să o luați aici este că lanțul de sferă de aplicare este determinat în timpul definiției, literalmente, în modul în care este scris codul. Transmiterea funcțiilor din interiorul codului dvs. nu va schimba lanțul de aplicare.


Închizăturile sunt cauzate de lanțul de domeniu

Luați ceea ce ați aflat despre lărgirea domeniului și despre domeniul de aplicare din acest articol și închiderea nu ar trebui să fie prea complicată pentru a înțelege. În următorul exemplu, creăm o funcție numită countUpFromZero. Această funcție returnează, de fapt, o referință la funcția copil inclusă în ea. Când această funcție a copilului (funcția imbricată) este invocată, ea are încă acces la domeniul de aplicare al funcției părinte din cauza lanțului de domeniu.

Mostră: sample117.html

 

De fiecare dată countUpFromZero este invocată funcția anonimă din (și returnată) din countUpFromZero funcția are încă acces la domeniul funcției părinte. Această tehnică, facilitată prin intermediul lanțului de aplicare, este un exemplu de închidere.


Concluzie

Dacă simți că am închideri prea simplificate, probabil că ai dreptate în acest gând. Dar am făcut așa intenționat, deoarece cred că părțile importante provin dintr-o înțelegere solidă a funcțiilor și a domeniului de aplicare, nu neapărat complexitatea contextului de execuție. Dacă aveți nevoie de o scufundare în profunzime în închideri, aruncați o privire la JavaScript Closures.

Cod