Skip to main content

Область видимості (scope)

Область видимості (scope) це механізм у JavaScript, який визначає, де в коді доступні змінні та функції, тобто з яких частин програми до них можна звернутися. Scope задається структурою коду: кожна функція і кожен блок створюють власне оточення, вкладене в зовнішнє.

Теорія

TL;DR

  • Глобальна область: оголошення поза функціями та блоками, доступні будь-де в коді.
  • Функціональна область: змінні, оголошені всередині функції, доступні лише всередині неї.
  • Блочна область: let і const усередині { } доступні тільки в межах цього блока.
  • var блочної області не має, він «випливає» до найближчої функції або в глобальний scope.
  • JavaScript використовує лексичну (статичну) область видимості: доступ визначає розташування функцій у коді, а не місце виклику.
  • Внутрішня функція запам'ятовує оточення, у якому була створена, це і є closure (замикання).

Швидкий приклад

javascript
const appName = 'Notes'; // глобальна область function render() { const title = 'Hello'; // функціональна область if (title) { const suffix = '!'; // блочна область console.log(title + suffix + ' ' + appName); // Hello! Notes } console.log(suffix); // ReferenceError: suffix is not defined } render(); console.log(title); // ReferenceError: title is not defined

Глобальна область (Global Scope)

Змінні, оголошені поза функціями або блоками, доступні повсюди в коді, зокрема всередині будь-якої функції.

javascript
let name = 'Tim'; // глобальна змінна function greet() { console.log('Hello, ' + name); // доступна тут } greet(); // Hello, Tim console.log(name); // доступна і тут

Глобальних змінних варто уникати: вони живуть увесь час роботи програми і будь-який модуль може їх перезаписати.

Функціональна область (Function Scope)

Змінні, оголошені за допомогою var, let або const усередині функції, доступні тільки всередині цієї функції.

javascript
function example() { let message = 'Inside function'; console.log(message); // працює } example(); console.log(message); // помилка: message is not defined

Кожен виклик функції створює нове оточення, тому локальні змінні різних викликів ніяк не перетинаються.

Блочна область (Block Scope)

Змінні, оголошені через let або const усередині блока { } (тіло if, for, while чи просто пара дужок), доступні лише в межах цього блока.

javascript
if (true) { const x = 10; let y = 20; var z = 30; // var не має блочної області } console.log(z); // 30 (var видно за межами блока) console.log(x); // помилка: x is not defined console.log(y); // помилка: y is not defined

Саме через це var у циклі поводиться не так, як let: var створює одну змінну на всю функцію, а let нову на кожну ітерацію.

Лексична область (Lexical Scope)

JavaScript використовує лексичну (статичну) область видимості: доступ до змінних визначається розташуванням функцій у коді, а не тим, звідки їх викликають.

javascript
function outer() { const outerVar = 'I am outside'; function inner() { console.log(outerVar); // має доступ до outerVar } return inner; } const fn = outer(); fn(); // "I am outside"

Тут inner запам'ятав оточення, у якому був створений, і це вже closure (замикання).

Пошук змінної йде вгору ланцюжком областей: власна область, потім зовнішня, і так до глобальної. Якщо ніде не знайдено, отримуємо ReferenceError.

Підсумок

Тип області видимостіДе створюєтьсяДоступність
ГлобальнаПоза функціями та блокамиСкрізь
ФункціональнаУсередині функціїТільки всередині функції
БлочнаУсередині { } (if, for тощо)Тільки в межах блока
ЛексичнаНа етапі написання кодуДоступ до змінних зовнішніх областей

Типові помилки

  • Вважати, що var має блочну область. Він її не має, тому змінна «витікає» з if чи for у всю функцію.
  • Плутати лексичну область із динамічною: те, звідки функцію викликали, на видимість змінних не впливає взагалі.
  • Створювати змінну без оголошення (count = 1) і мимоволі отримувати глобальну; у строгому режимі це ReferenceError.
  • Звертатися до let чи const до рядка оголошення: змінна вже в області, але в temporal dead zone, і це ReferenceError.
  • Покладатися на глобальні змінні для передавання даних між модулями замість параметрів і повернених значень.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.