Имате проблеми с разбирането на повдигане и затваряне? Това е така, защото не разбирате Scope много добре. Тази статия е 101 за обхвати.
Какво е обхват?
Обхватът е мястото, където търсим неща. Сега, какви са тези неща? идентификатори. Обхватите ни помагат да организираме тези идентификатори, да избягваме сблъсъци на имена и да използваме функции като повдигане и затваряне. Освен това разбирането на обхвата ни помага да пишем по-добър код.
JavaScript използва механизма за лексикален обхват, който се използва от повечето езици днес. Терминът лексикален идва от процес, наречен lexing, който се случва по време на компилиране за определяне на обхвати за всички идентификатори в нашия код.
Да, време за компилиране. JavaScript е „компилиран“ език.
Обхватите на JavaScript са декларативни, което означава, че когато поставите променлива във функция, вие изрично казвате на JavaScript, че обхватът на тази променлива е обхващащата функция.
function myScope() { var articleTopic = "scope"; }
Видове обхват
В JavaScript има 3 вида обхват:
- Глобален обхват
- Обхват на функцията
- Блоков обхват (въведен в ES6)
Ще прегледаме всеки тип и ще разберем как да ги използваме, за да подобрим нашите модели за кодиране.
Глобален обхват
Всичко, което не е във функционален блок ИЛИ, попада в глобалния обхват. Обекти като console
& windows
(в случая на браузъра) са налични в този обхват. Това е последното място, където JavaScript търси вашия идентификатор и ако не го намери тук, тогава дава ReferenceError
.
var food = "🍞"; console.log(food); // 🍞 function eat() { // accessing the global variable console.log("Eating " + food); // Eating 🍞 } eat(); // accessing the global identifier
Не е добра практика да имате много идентификатори в глобалния си обхват.
Има принцип в компютърните науки, наречен
🔥
принцип на най-малко излагане. Основно казва, че трябва да запазите всичко поверително и да изложите само минимално необходимото.
Това решава 3 основни проблема:
- Наименуване на сблъсъци
- Не можете случайно ИЛИ умишлено да злоупотребите с това нещо
- Вие се предпазвате от бъдещо преработване
За да направим това, трябва да използваме функции и блокови обхвати.
Обхват на функцията
Когато дефинирате функция, тя автоматично създава обхват. Без значение как е дефинирана функцията.
function eat() { var food = "🍞"; console.log(food); // 🍞 } console.log(food); // ReferenceError: food is not defined
Класовете в JavaScript са синтактична захар, където се използват функции под капака. Така че те също попадат в категорията на функционалния обхват.
💡
Съвет за по-добър код —var
се използва за дефиниране на променливи, които ще се използват във функцията.let
също може да постигне същото, но семантичноlet
иconst
трябва да се използват за блокови обхвати, аvar
трябва да се използва за обхват на ниво функция.
Обхват на блока
Проблемът с var
, който се използва на места като if-else
ИЛИ loop
е, че средата е извън фигурните скоби. Решение за този проблем беше въведено в ES6, т.е. блоков обхват заедно с let
и const
.
if (true) { let food = "🍞"; console.log(food); // 🍞 } console.log(food); // ReferenceError: food is not defined
Нещо, което може би не знаете е, че къдравите скоби сами по себе си не създават обхват. Когато let
ИЛИ const
се използва вътре в него, това имплицитно прави обхвата на блока.
💡
Един блок не трябва да бъде повече от 5–6 реда и използвайтеlet
&const
, когато работите върху дефинирането на променливи в обхвата на блока.
Поставете всички ваши променливи, дефинирани с помощта на let
& const
в горната част на обхвата на блока, защото не можете да получите достъп до тях, преди да бъдат инициализирани, в противен случай ще получите 💀
грешка TDZ (временова мъртва зона).
Понякога може да се случи, че искате променлива само за няколко реда код и дефинирате променлива в обхват на ниво функция. Вместо това създайте блок и обхват на променливата в обхвата на блока. Например:
function eat() { var food = "🍞"; // Pay for the food { let money = 100; console.log("Food cost: " + money); } // Eat the food console.log("Eating " + food); }
Вложени обхвати
Обхватите могат да бъдат вложени в други обхвати. Разгледайте следния пример на код:
{ // global scope function eat() { // eat scope function bite(person) { // bite scope } } }
Тук имаме 3 обхвата — глобален, eat
и bite
. Обхватът на функцията bite
е в обхвата на функцията eat
, който от своя страна е в глобалния обхват. Най-вътрешният обхват ще има достъп до идентификаторите на външните обхвати, но не и обратното. Следният пример го демонстрира:
var food = "🍞"; function eat() { var food = "🥪"; function bite(person) { console.log(person, food); } bite("👩🍳"); } eat(); // 👩🍳 🥪
Какво следва?
- „Веригиране на обхват и лексикална среда“
- Повдигане
- „затваряния“
- Модул модел