Jeśli na co dzień programujesz w JavaScripcie, na pewno spotkałeś się już z tajemniczym słowem kluczowym this
.
Z początku może wydawać się ono mega skomplikowane i dezorientujące.
Ale spokojnie 😉 W tym artykule dokładnie wyjaśnię, czym jest this
w JavaScript, jak działa w różnych kontekstach, oraz dlaczego warto wiedzieć na co wskazuje w różnych sytuacjach.
Pokażę Ci jak this
funkcjonuje w kontekście globalnym, w metodach obiektów, funkcjach strzałkowych, funkcjach konstruktorów, a także przy użyciu metod takich jak bind()
, call()
i apply()
.
No to lecimy 🚀
Wprowadzenie do this
w JavaScript 🧑💻
This
w języku JavaScript odnosi się do kontekstu, w którym funkcja została wywołana, i jego wartość może się różnić w zależności od tego, jak dana funkcja została zdefiniowana i użyta.
Oznacza to, że w jednym przypadku this
może odnosić się do obiektu globalnego, a w innym – do konkretnego obiektu lub instancji stworzonej przez funkcję konstruktora.
Początkowo może to brzmieć skomplikowanie, ale w rzeczywistości istnieją pewne wyraźne reguły, które pozwalają zrozumieć, w jaki sposób działa this
w różnych kontekstach.
Oto główne przypadki użycia this
:
- Globalny kontekst –
this
odnosi się do obiektu globalnego, czyliwindow
w przeglądarkach lubglobal
w Node.js. - Metody obiektów –
this
wskazuje na obiekt, który wywołuje daną metodę. - Funkcje strzałkowe (arrow functions) –
this
dziedziczy swój kontekst z miejsca, w którym funkcja została zdefiniowana, a nie z miejsca, gdzie została wywołana. - Funkcje konstruktorów –
this
odnosi się do nowo utworzonej instancji obiektu. - Metody
bind()
,call()
iapply()
– te metody pozwalają ręcznie manipulować wartościąthis
, ustawiając ją na dowolny obiekt.
Zrozumienie, jak działa this
, jest niezbędne, jeśli chcesz opanować JavaScript i tworzyć wydajne oraz elastyczne aplikacje.
This
w globalnym kontekście 🌐
W kontekście globalnym this
odnosi się do obiektu globalnego. W przypadku przeglądarek jest to obiekt window
, co oznacza, że gdy funkcja jest wywoływana w globalnym kontekście, this
domyślnie wskazuje na obiekt window
.
function showThis() {
console.log(this); // window object in the browser
}
showThis();
Jak widać powyżej, wywołanie funkcji showThis()
w przeglądarce spowoduje, że this
odniesie się do obiektu window
. W środowisku Node.js, wartość this
w kontekście globalnym wskazuje na obiekt global
.
Jednak kiedy pracujemy w trybie ścisłym (strict mode), wartość this
w globalnym kontekście zmienia się i zwraca undefined
. Zobaczmy, jak to działa.
Tryb ścisły (strict mode) 🚨
Kiedy włączasz tryb ścisły w JavaScript (dodając "use strict";
na początku pliku lub funkcji), JavaScript staje się bardziej restrykcyjny w niektórych sytuacjach, co może pomóc uniknąć błędów, które w normalnym trybie mogłyby nie zostać wykryte.
Jednym z efektów ubocznych włączenia trybu ścisłego jest zmiana zachowania this
w kontekście globalnym.
"use strict";
function showThisStrict() {
console.log(this); // undefined
}
showThisStrict();
Jak widzisz, po włączeniu trybu ścisłego, this
w kontekście globalnym zwraca undefined
zamiast odnosić się do obiektu window
.
Ma to na celu uniknięcie przypadkowych odwołań do globalnych obiektów, co jest częstym źródłem błędów w większych aplikacjach.
This
w metodach obiektów 🛠️
Kiedy funkcja jest wywoływana jako metoda obiektu, wartość this
odnosi się do tego konkretnego obiektu. Spójrzmy na poniższy przykład:
const person = {
name: "Alice",
introduce() {
console.log(`Hi! My name is ${this.name}`); // Hi! My name is Alice
},
};
person.introduce();
W tym przypadku this
odnosi się do obiektu person
, ponieważ to on wywołuje metodę introduce()
.
Oznacza to, że możemy korzystać z właściwości obiektu wewnątrz jego metod za pomocą słowa kluczowego this
.
Warto jednak zwrócić uwagę na jedno z częstych źródeł nieporozumień związanych z this
– sytuacje, w których definiujemy funkcję wewnętrzną w metodzie obiektu.
This
wewnątrz metod a funkcje wewnętrzne 🤯
Gdy w metodzie obiektu zdefiniujemy funkcję wewnętrzną, wartość this
wewnątrz tej funkcji może się zmienić. Przyjrzyjmy się temu w praktyce:
const person = {
name: "Alice",
introduce() {
function innerFunction() {
console.log(this.name); // undefined
}
innerFunction();
},
};
person.introduce();
Dlaczego zwracana wartość to undefined
? Dzieje się tak dlatego, że this
wewnątrz funkcji innerFunction()
odnosi się do obiektu globalnego (window
w przeglądarkach), a nie do obiektu person
.
Aby uniknąć takich problemów, często korzysta się z funkcji strzałkowych, które mają inny sposób traktowania this
.
Funkcje strzałkowe 🏹
Funkcje strzałkowe (arrow functions) w JavaScript wprowadzają kluczową różnicę w zachowaniu this
.
W tradycyjnych funkcjach wartość this
zależy od tego, jak funkcja została wywołana.
Natomiast funkcje strzałkowe posiadają leksykalne this
, co oznacza, że dziedziczą one wartość this
z miejsca, w którym zostały zdefiniowane.
Zobaczmy to na przykładzie:
const person = {
name: "Alice",
introduce() {
const innerFunction = () => {
console.log(this.name); // Alice
};
innerFunction();
},
};
person.introduce();
W tym przypadku, ponieważ innerFunction
jest funkcją strzałkową, this
dziedziczy wartość z otaczającego kontekstu, czyli z metody introduce()
, a co za tym idzie, this
wskazuje na obiekt person
.
Dzięki funkcjom strzałkowym unikamy problemów z this
w funkcjach wewnętrznych.
Jest to jeden z głównych powodów, dla których funkcje strzałkowe stały się tak popularne w nowoczesnym JavaScripcie.
This
w funkcjach konstruktorów 🏗️
Funkcje konstruktorów w JavaScript to specjalne funkcje, które są używane do tworzenia nowych instancji obiektów.
Kiedy funkcja jest wywoływana jako konstruktor (z użyciem słowa kluczowego new
), this
odnosi się do nowo utworzonej instancji obiektu.
Spójrzmy na przykład:
function Person(name, age) {
this.name = name;
this.age = age;
}
const john = new Person("John", 28);
console.log(john.name); // John
console.log(john.age); // 28
W tym przypadku, kiedy wywołujemy funkcję Person
za pomocą new
, tworzymy nową instancję obiektu, a this
odnosi się do tej właśnie instancji (john
).
Konstruktor pozwala na przypisywanie właściwości do nowo utworzonych obiektów.
Manipulowanie this za pomocą bind(), call() i apply() 🔄
Czasami potrzebujemy ręcznie zmodyfikować wartość this
dla danej funkcji.
W takich przypadkach możemy skorzystać z metod bind()
, call()
oraz apply()
. Oto, jak każda z nich działa w praktyce:
call()
– wywołuje funkcję z ustawionymthis
na dowolny obiekt, który podasz jako pierwszy parametr.
function greet() {
console.log(`Hello, my name is ${this.name}`);
}
const person = { name: "Tom" };
greet.call(person); // Hello, my name is Tom
apply()
– działa podobnie docall()
, ale zamiast przekazywać argumenty bezpośrednio, musisz je podać w formie tablicy.
function introduce(age, city) {
console.log(`${this.name} is ${age} years old and lives in ${city}`);
}
const person = { name: "Lucy" };
introduce.apply(person, [25, "New York"]); // Lucy is 25 years old and lives in New York
bind()
– tworzy nową funkcję, w którejthis
jest na stałe przypisany do wybranego obiektu.
function sayHello() {
console.log(`Hello, ${this.name}`);
}
const person = { name: "Kate" };
const boundSayHello = sayHello.bind(person);
boundSayHello(); // Hello, Kate
W odróżnieniu od call()
i apply()
, metoda bind()
nie wywołuje od razu funkcji, tylko zwraca nową funkcję z przypisanym this
, którą można wywołać później.
This a klasy ES6 👷♀️
Od czasu wprowadzenia klas w ES6, praca z funkcjami konstruktorów stała się bardziej intuicyjna. Klasy oferują czytelniejszą i bardziej zwięzłą składnię do tworzenia obiektów oraz pracy z this
.
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a noise`);
}
}
const dog = new Animal("Dog");
dog.speak(); // Dog makes a noise
Jak widzimy, w przypadku klas ES6, this
w metodach odnosi się do instancji obiektu utworzonej przez konstruktor (dog
w powyższym przykładzie).
Podsumowanie 🎯
This
w JavaScript jest niezwykle istotnym elementem, który pozwala na dynamiczne zarządzanie kontekstem wywołania funkcji.
W zależności od miejsca i sposobu wywołania funkcji, this
może odnosić się do obiektu globalnego, konkretnego obiektu lub nowo utworzonej instancji.
Zrozumienie, jak działa this
, jest kluczowe dla każdego programisty, który chce pisać efektywny i elastyczny kod w JavaScript.
Funkcje strzałkowe upraszczają pracę z this
, eliminując problem zmieniającego się kontekstu, a metody takie jak bind()
, call()
i apply()
dają pełną kontrolę nad przypisywaniem this
.
Wprowadzenie klas w ES6 dodatkowo upraszcza korzystanie z this
w konstruktorach, czyniąc kod bardziej czytelnym i zwięzłym.
Mam nadzieję, że ten artykuł pomógł Ci zrozumieć działanie this
w JavaScript i ułatwi dalszą pracę nad doskonaleniem Twojego rzemiosła.