Złożony obraz młodego mężczyzny pokazujący ekran jego komputera typu tablet

Słowo this w JavaScript – jak działa kontekst wykonania

8 min. czytania

Słowo kluczowe this w JavaScript odnosi się do obiektu stanowiącego aktualny kontekst wykonania funkcji — to, na co wskazuje, zależy od sposobu wywołania, a nie od miejsca definicji.

1. Czym jest this i kontekst wykonania?

W JavaScript this to specjalna zmienna tworzona przy każdym wywołaniu funkcji. Odnosi się do bieżącego kontekstu wykonania (execution context) — obiektu, z którym powiązana jest dana funkcja w momencie wywołania.

Najważniejsze zależności wyglądają tak:

  • Dynamiczne wiązaniethis nie jest ustalane przy definicji funkcji, lecz w chwili jej wywołania;
  • Sposób wywołania – wartość this zależy od tego, jak wywołasz funkcję (zwykła funkcja, metoda obiektu, konstruktor, handler zdarzenia itd.);
  • Funkcje strzałkowe – nie tworzą własnego this; dziedziczą je leksykalnie z otaczającego kontekstu.

Ta „ruchoma” natura this daje elastyczność, ale bywa źródłem błędów — szczególnie bez świadomości, co faktycznie wywołuje funkcję.

2. this w kontekście globalnym

Jeżeli użyjesz this poza funkcją (na najwyższym poziomie skryptu), będzie ono wskazywać na obiekt globalny — z ważnymi wyjątkami zależnymi od środowiska:

  • Przeglądarkathis to zwykle window;
  • globalThis – preferowane, ujednolicone odwołanie do obiektu globalnego;
  • Node.js – w pliku modułu CommonJS this wskazuje na module.exports, a nie na obiekt globalny.

Przykład w przeglądarce:

console.log(this === window); // true
console.log(globalThis === window); // true w przeglądarce

Nadmierne „zaśmiecanie” globalnego scope’u pogarsza utrzymanie kodu — także w obszarach dostępności (np. logika klawiaturowa, pułapki fokusu, zarządzanie ARIA).

3. this w zwykłych funkcjach — zależność od sposobu wywołania

W klasycznych funkcjach (nie-strzałkowych) wartość this wynika wyłącznie z tego, jak funkcja została wywołana.

Przykład zwykłego wywołania funkcji:

function showThis() {
console.log(this);
}

showThis(); // w przeglądarce: window (w trybie nie-ścisłym)

Gdy funkcja jest wywołana „na goło” (showThis()), w trybie nie-ścisłym this wskazuje na window, a w trybie ścisłym ("use strict") jest undefined.

Tryb ścisły pomaga wyłapać przypadki, gdy omyłkowo korzystasz z globalnego this.

4. this w metodach obiektów

Gdy funkcja jest wywołana jako metoda obiektu, this zazwyczaj wskazuje na obiekt, na którym wywołano metodę.

Przykład metody obiektu:

const user = {
name: 'Ania',
greet() {
console.log(`Cześć, jestem ${this.name}`);
}
};

user.greet(); // this === user

Tutaj this wewnątrz greet wskazuje na user, ponieważ metoda została wywołana jako user.greet().

Zmiana referencji nie zmienia tego, na co wskaże this przy „gołym” wywołaniu metody:

const fn = user.greet;
fn(); // w trybie nie-ścisłym: this === window; w ścisłym: this === undefined

Decyduje sposób wywołania, a nie miejsce definicji.

5. this w konstruktorach i klasach

Funkcje wywołane z operatorem new pełnią rolę konstruktorów — wtedy this wskazuje na nowo tworzony obiekt.

Przykład konstruktora funkcji:

function Button(label) {
this.label = label;
}

const btn = new Button('Zapisz');
console.log(btn.label); // "Zapisz"

Przy new silnik tworzy nowy obiekt, ustawia go jako this i (domyślnie) go zwraca.

Analogicznie działa to w klasach:

class Dialog {
constructor(title) {
this.title = title;
}
open() {
console.log(`Otwieram: ${this.title}`);
}
}

const dialog = new Dialog('Ustawienia');
dialog.open(); // this === dialog

W komponentach UI (dialogi ARIA, menu, karuzele) błędne this potrafi „przenieść” operacje na niewłaściwy element — np. fokus czy atrybuty aria-*.

6. this w zdarzeniach DOM — i konsekwencje dla dostępności

W handlerze zdarzenia (gdy używasz zwykłej funkcji), this zwykle wskazuje na element, do którego przypięto handler.

Przykład z addEventListener:

const button = document.querySelector('button');

button.addEventListener('click', function (event) {
console.log(this === button); // true
});

To ułatwia aktualizację atrybutów ARIA czy klas CSS konkretnego elementu.

Przykład — dostępny przełącznik (toggle):

<button class="menu-toggle" aria-expanded="false" aria-controls="main-menu">
Menu
</button>
<nav id="main-menu" hidden>...</nav>

Przykładowy skrypt obsługi przełącznika:

document.querySelector('.menu-toggle')
.addEventListener('click', function () {
const expanded = this.getAttribute('aria-expanded') === 'true';
this.setAttribute('aria-expanded', String(!expanded));

const menu = document.getElementById(
this.getAttribute('aria-controls')
);
menu.hidden = expanded;
});

Tutaj this wskazuje na konkretny kliknięty przycisk — dzięki temu ten sam kod działa dla wielu przełączników. Gdyby użyć funkcji strzałkowej, this nie wskazywałoby na element, co mogłoby zepsuć logikę dostępności.

Pamiętaj: w handlerach zdarzeń często bezpieczniej korzystać z event.currentTarget (czasem też event.target) zamiast polegać wyłącznie na this.

7. this w funkcjach strzałkowych

Funkcje strzałkowe (=>) nie tworzą własnego this; dziedziczą je z otaczającego kontekstu leksykalnego.

Przykład dziedziczenia this w callbacku:

const obj = {
name: 'Panel',
init() {
setTimeout(() => {
console.log(this.name); // "Panel"
}, 100);
}
};

obj.init();

W powyższym kodzie this wewnątrz funkcji strzałkowej wskazuje na to samo, co w metodzie init (czyli na obj). Gdyby użyć klasycznej funkcji, this w setTimeout byłoby window (lub undefined w trybie ścisłym).

Funkcje strzałkowe świetnie nadają się do callbacków (np. setTimeout, Promise, fetch), bo eliminują potrzebę ręcznego .bind().

Nie używaj funkcji strzałkowych jako metod wymagających „własnego” this ani jako konstruktorów — nie współpracują z new.

W handlerach zdarzeń DOM funkcje strzałkowe mogą wprowadzać chaos, jeśli kod zakłada, że this to element wywołujący — wtedy lepiej użyć zwykłej funkcji lub event.currentTarget.

8. Wymuszanie kontekstu: call, apply, bind

JavaScript pozwala ręcznie ustawić wartość this przy wywołaniu funkcji.

call i apply

Obie metody wywołują funkcję natychmiast z określonym this:

Przykład użycia call i apply:

function showName(prefix) {
console.log(prefix, this.name);
}

const user = { name: 'Ola' };

showName.call(user, 'Użytkownik:'); // this === user
showName.apply(user, ['Użytkownik:']); // this === user

call(thisArg, a, b) przekazuje argumenty pojedynczo, a apply(thisArg, [a, b]) w tablicy.

bind

bind tworzy nową funkcję z na stałe związanym this (nie wywołuje jej od razu).

Przykład bind w praktyce:

function log() {
console.log(this.id);
}

const element = { id: 'header' };
const boundLog = log.bind(element);

boundLog(); // zawsze this === element

Możesz też częściowo „podstawić” argumenty (partial application). To przydatne, gdy przekazujesz metody klasowe jako callbacki lub rejestrujesz handlery bez utraty właściwego this.

9. this, moduły i tryb ścisły

W nowoczesnym ekosystemie (ES Modules, bundlery) this zachowuje się odmiennie w zależności od typu skryptu:

  • Moduły ES (type="module") – kod działa w trybie ścisłym; this na najwyższym poziomie to undefined;
  • Skrypty klasycznethis na poziomie globalnym to window;
  • Node.js (CommonJS) – na najwyższym poziomie pliku this odwołuje się do module.exports.

W aplikacjach webowych nie zakładaj this === window na najwyższym poziomie plików modułowych; jeśli musisz odwołać się do globalnego obiektu, użyj globalThis.

10. Typowe pułapki związane z this — i jak ich unikać

Utrata kontekstu metod

Częsty błąd wygląda tak:

const widget = {
label: 'Filtrowanie wyników',
init() {
console.log(this.label);
}
};

const initFn = widget.init;
initFn(); // this: window/undefined, a nie widget

Rozwiązanie 1 — użyj bind:

const initFnBound = widget.init.bind(widget);
initFnBound();

Rozwiązanie 2 — przekaż wywołanie przez funkcję strzałkową:

someApi.onReady(() => widget.init());

Funkcja strzałkowa jako metoda oczekująca „własnego” this

Przykład błędu:

const counter = {
value: 0,
increment: () => {
this.value++; // tu this NIE wskazuje na counter
}
};

Poprawna wersja z klasyczną metodą:

const counter = {
value: 0,
increment() {
this.value++;
}
};

Handlery zdarzeń z funkcją strzałkową

Przykład potencjalnego problemu:

button.addEventListener('click', () => {
console.log(this); // raczej nie to, czego oczekujemy
});

Lepiej użyć zwykłej funkcji, jeśli operujesz na elemencie przez this:

button.addEventListener('click', function () {
this.setAttribute('aria-pressed', 'true');
});

Ewentualnie korzystaj z event.currentTarget — jest przewidywalne niezależnie od typu funkcji:

button.addEventListener('click', (event) => {
event.currentTarget.setAttribute('aria-pressed', 'true');
});

this a dostępność

Błędne zrozumienie this realnie wpływa na dostępność:

  • aktualizowanie nie tego elementu (np. aria-expanded, aria-live, role) przez handler operujący na mylnym this,
  • przypięcie logiki klawiaturowej (strzałki w menu, Tab w dialogu) do niewłaściwego elementu,
  • nieprawidłowe przenoszenie fokusu (focus()) przy metodzie zakładającej inne this.

W krytycznej logice (nawigacja, dialogi, menu, przełączniki) preferuj jawne referencjeevent.currentTarget, document.getElementById — zamiast domyślnych zachowań this.

Regularnie uruchamiaj testy z klawiaturą i czytnikami ekranu, by szybko wykrywać błędy kontekstu.

11. Najważniejsze zasady pracy z this w pigułce

  • Definicjathis to obiekt stanowiący kontekst wywołania funkcji, ustalany w momencie wywołania;
  • Kontekst globalny – w skryptach klasycznych this to window, w modułach bywa undefined; preferuj globalThis;
  • Zwykłe wywołanie – „goła” funkcja: window lub undefined (w strict mode);
  • Metoda obiektuthis wskazuje na obiekt, na którym wywołano metodę;
  • Konstruktor – z new this to nowo tworzony obiekt;
  • Zdarzenia DOM – w zwykłej funkcji this to element z przypiętym handlerem; ma to bezpośredni wpływ na dostępność;
  • Funkcje strzałkowe – nie mają własnego this, dziedziczą je z zewnętrznego kontekstu; dobre do callbacków, nie do metod wymagających własnego this;
  • call / apply – wywołują funkcję natychmiast z ustawionym this;
  • bind – zwraca nową funkcję z na stałe związanym this;
  • Dostępność – w złożonych komponentach interfejsu unikaj niejasnych zależności od this; stosuj jawne referencje i przemyślaną strukturę zdarzeń.