Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Контекст функції». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Контекст функції це об'єкт, на який посилається ключове слово `this` усередині функції під час її виконання.** Контекст визначається в момент виклику, а не в момент оголошення: звичайний виклик дає глобальний об'єкт або `undefined` у strict mode, виклик як метод дає сам об'єкт, `new` дає новий екземпляр, а `call`, `apply` і `bind` задають `this` вручну. Стрілкові функції власного `this` не мають і беруть його з зовнішнього лексичного оточення. ```javascript const user = { name: "Alice", sayHi() { console.log(this.name); }, }; user.sayHi(); // "Alice", this === user const hi = user.sayHi; hi(); // undefined, контекст втрачено ``` **Ключове:** хто викликає функцію, той і стає `this`, тому контекст легко загубити, передавши метод як звичайне посилання.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**Контекст функції це об'єкт, на який посилається ключове слово `this` усередині функції під час її виконання.** Головне правило: контекст визначається в момент виклику функції, а не в момент її оголошення. ## Теорія ### TL;DR - `this` це посилання на об'єкт, у контексті якого зараз виконується функція. - Значення `this` залежить від **способу виклику**, а не від місця оголошення. - Звичайний виклик: глобальний об'єкт (`window` у браузері) або `undefined` у strict mode. - Виклик як метод `obj.method()`: контекстом стає `obj`. - Виклик через `new`: контекстом стає новий створений об'єкт. - `call`, `apply`, `bind`: контекст задається вручну. - Стрілкові функції власного `this` не мають і беруть його з зовнішнього оточення. ### Швидкий приклад ```javascript function showThis() { console.log(this); } showThis(); // у звичайному виклику контекстом є глобальний об'єкт ``` У браузері в нестрогому режимі: ```javascript this === window; ``` У Node.js усередині звичайної функції в строгому режимі: ```javascript this === undefined; ``` ### Контекст залежить від способу виклику | Як викликаємо функцію | Яким буде `this` | | --- | --- | | Звичайний виклик `func()` | Глобальний об'єкт (`window`) або `undefined` у strict mode | | Виклик як метод `obj.method()` | Об'єкт `obj` | | Через `new` | Новий створений об'єкт | | Через `call` / `apply` / `bind` | Вказаний вручну об'єкт | | У стрілковій функції | `this` береться з зовнішнього контексту (лексично) | Звичайний виклик, тобто глобальний контекст: ```javascript function test() { console.log(this); } test(); // window (або undefined у strict mode) ``` Виклик як метод об'єкта: ```javascript const user = { name: "Alice", sayHi() { console.log(this.name); }, }; user.sayHi(); // "Alice" ``` Тут `this` посилається на об'єкт **user**, бо функцію викликано саме як `user.sayHi()`. ### Втрата контексту ```javascript const user = { name: "Alice", sayHi() { console.log(this.name); }, }; const hi = user.sayHi; hi(); // undefined, this втрачено ``` Чому так: - Ми передали **посилання на функцію**, але не сам об'єкт. - Виклик `hi()` це звичайний виклик, без контексту `user`. Виправлення через `bind`: ```javascript const hi = user.sayHi.bind(user); hi(); // "Alice" ``` Та сама пастка трапляється, коли метод передають як колбек: `setTimeout(user.sayHi, 100)` або `button.addEventListener("click", user.sayHi)`. ### Контекст при виклику через new ```javascript function User(name) { this.name = name; } const u = new User("Alice"); console.log(u.name); // "Alice" ``` Тут `this` вказує на **новий створений об'єкт** (`u`). Оператор `new` створює порожній об'єкт, робить його контекстом виклику і повертає його, якщо функція явно не повернула інший об'єкт. ### call, apply і bind ```javascript function greet() { console.log(this.name); } const user = { name: "Maria" }; greet.call(user); // "Maria" greet.apply(user); // "Maria" const boundGreet = greet.bind(user); boundGreet(); // "Maria" ``` | Метод | Що робить | | --- | --- | | `call(thisArg, arg1, arg2, ...)` | викликає функцію з указаним `this` і аргументами через кому | | `apply(thisArg, [args])` | те саме, але аргументи передаються масивом | | `bind(thisArg)` | повертає нову функцію із зафіксованим `this`, не викликаючи її одразу | ### Стрілкові функції та підсумок ```javascript const obj = { name: "Alice", arrow: () => console.log(this.name), regular() { console.log(this.name); }, }; obj.arrow(); // undefined, this це зовнішній контекст, не obj obj.regular(); // "Alice" ``` Важливо: - Стрілкові функції **не мають власного** `this`. - Вони «беруть» `this` із зовнішнього лексичного оточення, тобто звідти, де їх створено. - Через це `call`, `apply` і `bind` не змінюють `this` у стрілковій функції. Підсумкова таблиця: | Ситуація | Яким буде `this` | | --- | --- | | Звичайний виклик | `window` або `undefined` | | Метод об'єкта | Сам об'єкт | | `new` | Новий екземпляр | | `call`, `apply`, `bind` | Вказаний вручну об'єкт | | Стрілкова функція | Успадковує `this` ззовні | > Контекст функції це «власник виклику»: хто викликає функцію, той і стає `this`. ### Типові помилки - **Вважати, що `this` визначається місцем оголошення.** Ні, він визначається місцем і способом виклику. - **Передавати метод як колбек без прив'язки.** `setTimeout(user.sayHi, 100)` втрачає контекст. Треба `user.sayHi.bind(user)` або стрілкова обгортка `() => user.sayHi()`. - **Робити метод об'єкта стрілковою функцією.** Тоді `this` вказує не на об'єкт, а на зовнішнє оточення, і `this.name` дасть `undefined`. - **Плутати `call` і `apply`.** `call` приймає аргументи через кому, `apply` приймає масив. - **Очікувати, що `bind` можна перевизначити.** Прив'язану функцію не можна перепривʼязати повторним `bind` або `call`: перша прив'язка перемагає. - **Забувати про strict mode.** У модулях і класах код завжди строгий, тому в звичайному виклику там буде `undefined`, а не `window`.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.