Co to jest this w JavaScript?🤔

JavaScript

readTime

7 min

Co to jest this w JavaScript?🤔

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 kontekstthis odnosi się do obiektu globalnego, czyli window w przeglądarkach lub global w Node.js.
  • Metody obiektówthis 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ówthis odnosi się do nowo utworzonej instancji obiektu.
  • Metody bind(), call() i apply() – 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.

javascript
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.

javascript
"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:

javascript
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:

javascript
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:

javascript
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:

javascript
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 ustawionym this na dowolny obiekt, który podasz jako pierwszy parametr.
javascript
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 do call(), ale zamiast przekazywać argumenty bezpośrednio, musisz je podać w formie tablicy.
javascript
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órej this jest na stałe przypisany do wybranego obiektu.
javascript
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.

javascript
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.

authorImg

Witek Pruchnicki

Z pasją dzielę się wiedzą o programowaniu i nie tylko na różne sposoby