Имате проблеми с разбирането на повдигане и затваряне? Това е така, защото не разбирате 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(); // 👩‍🍳 🥪

Какво следва?