Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Складові контексту виконання». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Контекст виконання складається з трьох компонентів: Variable Environment (зберігає оголошення `var` і `function`), Lexical Environment (зберігає `let` і `const` плюс посилання на зовнішнє оточення, тобто scope chain) і This Binding (значення `this`, яке залежить від способу виклику функції).** Саме посилання на зовнішнє лексичне оточення робить можливими замикання (closures). ```javascript Execution Context { LexicalEnvironment: { EnvironmentRecord: { let, const }, OuterEnvironmentReference }, VariableEnvironment: { EnvironmentRecord: { var, function }, OuterEnvironmentReference }, ThisBinding: <value of this> } ``` **Ключове:** VE, це `var` і `function`; LE, це `let`/`const` плюс ланцюжок областей видимості; This Binding, це `this`.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**Контекст виконання (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`.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.