Пошук уроків, статей та іншого контенту
Дізнайтеся, як JavaScript визначає доступність змінних на основі місця, де функція була створена. Це поняття стане фундаментом для подальшого розуміння замикань і роботи вкладених функцій.
Лексична область видимості визначає, де саме в коді JavaScript можна звернутися до змінної.
Назва «лексична» означає, що область видимості визначається за місцем, де код написано. JavaScript аналізує вкладеність блоків і функцій у початковому коді, а не те, звідки функцію викликали.
Наприклад:
const message = "Привіт";
function greet() {
console.log(message);
}
greet(); // ПривітФункція greet була створена в області, де доступна змінна message, тому вона може її використати.
Коли всередині блоку або функції створюється інша область видимості, внутрішній код може звертатися до змінних із зовнішньої області.
const language = "JavaScript";
function showLanguage() {
const version = "ES2025";
console.log(language); // JavaScript
console.log(version); // ES2025
}
showLanguage();Функція showLanguage має доступ до:
власних змінних;
змінних зовнішньої області;
глобальних змінних.
Зовнішній код не має доступу до локальних змінних функції:
function createMessage() {
const message = "Приватне повідомлення";
console.log(message); // Приватне повідомлення
}
createMessage();
console.log(message); // ReferenceErrorЗмінна message існує лише всередині createMessage.
Якщо JavaScript не знаходить змінну в поточній області, він шукає її у зовнішній області. Потім пошук продовжується далі, аж до глобальної області.
const appName = "Мій застосунок";
function startApp() {
const userName = "Олена";
function showInfo() {
const message = "Вітаємо!";
console.log(message); // поточна область
console.log(userName); // область startApp
console.log(appName); // глобальна область
}
showInfo();
}
startApp();Функція showInfo бачить змінні з усіх зовнішніх областей.
Напрямок доступу працює лише зсередини назовні:
function outer() {
const outerValue = "Зовнішнє значення";
function inner() {
const innerValue = "Внутрішнє значення";
console.log(outerValue); // доступ дозволено
}
inner();
console.log(innerValue); // ReferenceError
}
outer();inner може використовувати outerValue, але outer не може використовувати innerValue.
Змінні, оголошені за допомогою let і const, мають область видимості блоку. Блоком є код між фігурними дужками {}.
if (true) {
const message = "Усередині блоку";
console.log(message); // Усе працює
}
console.log(message); // ReferenceErrorТакож область видимості створюють цикли:
for (let index = 0; index < 3; index++) {
console.log(index);
}
console.log(index); // ReferenceErrorЗмінна index доступна лише всередині циклу.
Функція також створює власну область видимості:
function calculate() {
const result = 10 + 5;
console.log(result); // 15
}
calculate();
console.log(result); // ReferenceErrorЗмінна result локальна для функції.
Розглянемо приклад:
const value = "глобальне значення";
function printValue() {
console.log(value);
}
function run() {
const value = "локальне значення";
printValue();
}
run(); // глобальне значенняМоже здатися, що printValue має використати value з run, адже функцію викликали всередині run. Але це не так.
Функція printValue була створена в глобальній області, тому вона шукає value саме там. Місце виклику функції не змінює її лексичну область видимості.
Саме це відрізняє лексичну область видимості від підходу, за якого змінні шукаються за ланцюжком викликів.
Якщо у внутрішній області оголошено змінну з такою самою назвою, вона затіняє змінну із зовнішньої області.
const color = "синій";
function showColor() {
const color = "зелений";
console.log(color); // зелений
}
showColor();
console.log(color); // синійУсередині showColor JavaScript знаходить локальну змінну color першою, тому не звертається до глобальної.
Затінення може відбуватися на кількох рівнях:
const value = "глобальне";
function first() {
const value = "перше";
function second() {
const value = "друге";
console.log(value); // друге
}
second();
}
first();Пошук завжди починається з найближчої області.
var, let і область видимостіlet і const мають блочну область видимості, а var — область видимості функції.
if (true) {
let letValue = "let";
const constValue = "const";
var varValue = "var";
}
console.log(varValue); // var
console.log(letValue); // ReferenceError
console.log(constValue); // ReferenceErrorvarValue доступна після завершення блоку if, тому що var не обмежується блоком. Натомість letValue і constValue існують лише всередині if.
У сучасному JavaScript зазвичай використовують const і let:
const — якщо змінну не потрібно переприсвоювати;
let — якщо значення змінюватиметься;
var — переважно в застарілому коді або під час вивчення особливостей JavaScript.
У наступному прикладі кожна функція має доступ до своїх локальних змінних і змінних із зовнішніх областей:
const currency = "грн";
function createReceipt(productName, price) {
const tax = price * 0.2;
function printReceipt() {
const total = price + tax;
console.log(`Товар: ${productName}`);
console.log(`Ціна: ${price} ${currency}`);
console.log(`Податок: ${tax} ${currency}`);
console.log(`Разом: ${total} ${currency}`);
}
printReceipt();
}
createReceipt("Книга", 500);Функція printReceipt має доступ до:
total — власна змінна;
price, tax, productName — змінні з createReceipt;
currency — змінна із зовнішньої області.
Водночас змінна total недоступна безпосередньо в createReceipt.
Лексична область видимості є основою замикань. Внутрішня функція може зберігати доступ до змінних зовнішньої функції навіть після завершення її виконання.
function createCounter() {
let count = 0;
return function () {
count += 1;
return count;
};
}
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3Внутрішня функція продовжує бачити count, тому що була створена в області, де ця змінна існувала. Детально замикання розглядають окремо, але його робота безпосередньо залежить від лексичної області видимості.
const name = "Анна";
function sayHello() {
console.log(name);
}
function run() {
const name = "Олег";
sayHello();
}
run(); // АннаФункція sayHello використовує name із місця створення, а не з місця виклику.
function getUser() {
const user = "Олена";
}
getUser();
console.log(user); // ReferenceErrorЛокальні змінні доступні лише у своїй області.
const userName = "Анна";
function showUser() {
const userName = "Олег";
console.log(userName); // Олег
}
showUser();Однакові назви можуть ускладнювати читання коду. Якщо затінення не потрібне, краще використовувати різні зрозумілі назви.
console.log(message); // ReferenceError
const message = "Привіт";let і const не можна використовувати до моменту їхнього оголошення.
Для кожної змінної можна поставити три запитання:
У якій області її оголошено?
Чи перебуває поточний код у цій області або в одній із внутрішніх областей?
Чи немає ближчої змінної з такою самою назвою?
Якщо змінна не знайдена в жодній доступній області, JavaScript викине помилку ReferenceError.
Лексична область видимості визначається місцем, де код написано.
Вкладена функція має доступ до змінних зовнішніх областей.
Зовнішня функція не має доступу до локальних змінних вкладеної функції.
JavaScript шукає змінні від поточної області назовні, утворюючи ланцюжок областей видимості.
Місце виклику функції не змінює її лексичну область видимості.
let і const мають блочну область видимості, а var — функціональну.
Локальна змінна може затінити змінну з таким самим іменем у зовнішній області.
Лексична область видимості є фундаментом для розуміння замикань.