Skip to main content

Складові контексту виконання

Контекст виконання (Execution Context) у JavaScript складається з трьох основних компонентів: це внутрішні структури, які рушій створює для роботи вашого коду. Кожен контекст, глобальний чи функції, містить Variable Environment, Lexical Environment і This Binding.

Теорія

TL;DR

  • Variable Environment (VE): оголошення через var і function.
  • Lexical Environment (LE): оголошення через let і const плюс посилання на зовнішнє оточення.
  • This Binding: значення this, визначається способом виклику функції.
  • Ланцюжок OuterEnvironmentReference утворює scope chain і робить можливими замикання (closures).
  • Обидва оточення мають свій Environment Record, тому var і let живуть у різних записах одного контексту.

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

javascript
let x = 10; function outer() { let y = 20; function inner() { let z = 30; console.log(x, y, z); // 10 20 30 } inner(); } outer();

Lexical Environment функції inner() містить:

  • власну змінну z;
  • посилання на оточення outer() (де є y);
  • і через нього посилання на глобальне оточення (де є x).

Саме Lexical Environment робить можливими замикання (closures).

Variable Environment

Зберігає змінні й функції, оголошені через var і function (не let/const).

  • Визначається під час створення контексту.
  • Використовується для ініціалізації змінних і функцій.
  • Доступний лише всередині поточного контексту.

Приклад:

javascript
function test() { var a = 10; function inner() {} }

Тут a та inner, це частина Variable Environment функції test.

Lexical Environment

Відповідає за пошук змінних і за замикання. Зберігає:

  • змінні, оголошені через let і const;
  • посилання на зовнішні оточення (outer lexical environment reference);
  • саму функцію як «лексичне оточення».

Це можна уявляти як «ланцюжок областей видимості» (scope chain): якщо імені немає в поточному записі, пошук іде на рівень вище, і так до глобального оточення.

This Binding

Визначає, на який об'єкт посилається this у цьому контексті. Залежить від того, як викликано функцію:

Спосіб викликуЗначення this
Глобально (у браузері)window
У функції (строгий режим)undefined
У методі об'єктасам об'єкт
Через call, apply, bindзначення, передане вручну
У стрілковій функціїбереться із зовнішнього контексту

Приклад:

javascript
const obj = { name: "Tim", show() { console.log(this.name); } }; obj.show(); // this = obj, тому "Tim"

Зведена структура

Кожен контекст виконання виглядає приблизно так:

javascript
Execution Context { LexicalEnvironment: { EnvironmentRecord: { let, const }, OuterEnvironmentReference: <посилання на зовнішнє LE> }, VariableEnvironment: { EnvironmentRecord: { var, function }, OuterEnvironmentReference: <посилання на зовнішнє LE> }, ThisBinding: <значення this> }

Приклад візуально

javascript
let a = 1; function outer() { var b = 2; function inner() { let c = 3; console.log(a, b, c); } inner(); } outer();

Коли викликається inner():

  • Створюється новий Execution Context, який містить:

    • Variable Environment: []
    • Lexical Environment: { c: 3 }
    • This Binding: undefined (строгий режим)
  • Він має Outer Environment Reference, що веде до outer, а звідти до глобального оточення, і саме це дозволяє знайти b та a.

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

  • Думати, що let і const живуть у Variable Environment. Вони потрапляють у Lexical Environment; VE тримає лише var і оголошення функцій.
  • Вважати, що let не піднімається (hoisting). Піднімається, але до рядка оголошення перебуває в temporal dead zone, і звернення до нього кидає ReferenceError.
  • Плутати This Binding із лексичним оточенням. Стрілкова функція взагалі не має власного this, вона бере його із зовнішнього контексту.
  • Думати, що scope chain будується під час виклику. Посилання OuterEnvironmentReference визначається місцем оголошення функції в коді, а не тим, звідки її викликали.
  • Забувати про строгий режим. У модулях і в класах код завжди строгий, тому this у звичайному виклику функції буде undefined, а не window.

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

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

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