JS - SŁOWO KLUCZOWE THIS

JS - SŁOWO KLUCZOWE THIS

SŁOWO KLUCZOWE THIS = REFERENCJA DO KONTEKSTU

Słowo this wskazuje na tak zwany execution context, czyli miejsce, kontekst, w którym wywoływany jest dany kawałek kodu.
Wartość this nie jest stała i zależy od sposobu wywołania funkcji, np. w metodach obiektów this wskazuje na ten obiekt. Kluczowa jest również różnica między tradycyjnymi funkcjami a funkcjami strzałkowymi, które nie mają własnego this, a zamiast tego dziedziczą je z otaczającego zakresu.

W jakich sytuacjach stosuje się this w języku JavaScript?

  • Tworzenie obiektów za pomocą konstruktorówthis pozwala na odniesienie się do instancji tworzonego obiektu, umożliwiając przypisywanie właściwości i metod specyficznych dla tej instancji.
  • Metody obiektów. W metodach obiektów, this odnosi się do obiektu, na którym metoda została wywołana. Pozwala to na interakcję z innymi właściwościami i metodami tego obiektu.
  • Łańcuchowanie metod. Użycie this w metodach obiektu pozwala na ich łańcuchowanie poprzez zwracanie samego siebie (return this;), co zwiększa czytelność i efektywność kodu.
  • Obsługa zdarzeń w przeglądarkach: W funkcjach obsługujących zdarzenia, this może odnosić się do elementu DOM, na którym zdarzenie zostało wywołane, umożliwiając łatwą manipulację elementem.

    Jak działa this w zależności od kontekstu:
    - kontekst globalny
    - kontekst funkcji
    - kontekst metody
    - kontekst konstruktora
    - kontekst event handlera
  • kontekst globalny - this poza jakąkolwiek funkcją
    Jeśli chcemy wywołać globalną zmienną, do której została przypisana wartość this bez żadnego dodatkowego kontekstu to otrzymamy obiekt "Window", który po prostu opisuje okno przeglądarki.
  • kontekst funkcji (non-strict mode)
    Jeśli nie przekazujemy żadnej dodatkowej wartości/argumentu w funkcji, tylko wywołujemy this to również otrzymamy obiekt "Window".
  • kontekst funkcji ale w strict mode
    W momencie, gdy w funkcji zostanie użyty przełącznik "use strict" to nie da się wyciągnąć this z kontekstu globalnego i otrzymamy UNDEFINED
  • kontekst funkcji zagnieżdżonej
    Jeśli wołamy this w funkcji zagnieżdżonej bez podanych argumentów to otrzymamy znowu obiekt "Window", tak samo jak w przypadku funkcji non-strict mode.
    Gdybyśmy mieli zagnieżdżone funkcje strict mode to otrzymamy w obydwu przypadkach UNDEFINED


PROBLEM: THIS W CALLBACK
W sytuacji, gdy przekazujemy samą funkcję do funkcji to globalnie znowu otrzymamy "Widow", ale po przekazaniu czegoś do funkcji to this zmienia się na funkcję "pokaż this":

DO CZEGO SŁUŻY BIND W PRZYPADKU METODY THIS?

  • W funkcji jako metodzie obiektu:
    W standardowej funkcji this określa się poprzez sposób wywołania tej funkcji. Jeśli funkcja jest wywoływana jako metoda obiektu, this wskazuje na ten obiekt.
const person = {
    name: 'Jan',
    greet: function() {
        console.log('Cześć, jestem ' + this.name);
    }
};

person.greet(); // Wyświetla: "Cześć, jestem Jan"
  • W funkcji strzałkowej (=>):
    W przypadku użycia funkcji strzałkowej, this jest powiązana leksykalnie.
    Tutaj this nie ma własnego kontekstu, lecz dziedziczy go z otaczającego, zewnętrznego zakresu. Jest to bardzo przydatne w sytuacjach, gdy chcemy zachować kontekst funkcji wywołującej, np. w callbackach (wywołaniach zwrotnych).
    UWAGA! W tym kontekście this nie nadaje się do używania jako metoda obiektu, ponieważ nie będzie wskazywać na sam obiekt. 
const person = {
    name: 'Jan',
    greet: () => {
        console.log('Cześć, jestem ' + this.name);
    }
};

person.greet(); // W przeglądarce wyświetli: "Cześć, jestem ", ponieważ `this` wskazuje na globalny obiekt window
  • Konstruktor i new – this w JavaScript wskazuje na nowy obiekt

Gdy funkcja konstruktora jest wywoływana z użyciem newthis wskazuje na nowo utworzony obiekt.

function Person(name) {
    this.name = name;
    this.greet = function() {
        console.log('Cześć, jestem ' + this.name);
    };
}

const jan = new Person('Jan');
jan.greet(); // Wyświetla: "Cześć, jestem Jan"

W tym kodzie definiuje się funkcję konstruktora Person, która inicjalizuje nowe obiekty z własnością name i metodą greet.

Przy użyciu słowa kluczowego new tworzony jest nowy obiekt jan na podstawie konstruktora Person, przy czym własność name ustawiona jest na „Jan”. Następnie wywoływana jest metoda greet obiektu jan, która wyświetla powitanie z użyciem imienia przechowywanego w właściwości name tego obiektu.

Explicit binding

Metoda bind w JavaScript umożliwia tworzenie nowej funkcji, która ma związany z nią określony kontekst (this) oraz sekwencję argumentów pierwotnej funkcji. Składnia metody bind jest następująca:

let związanaFunkcja = funkcja.bind(kontekst, [arg1], [arg2], [...]);

W tym przypadku funkcja to funkcja, której kontekst chcemy związać, a kontekst to wartość, która ma być przypisana do this w związanej funkcji.

Rozważmy prosty przykład:

let obiekt = {
    x: 42,
    getX: function() {
        return this.x;
    }
};

let niezwiązanaFunkcja = obiekt.getX;
let związanaFunkcja = niezwiązanaFunkcja.bind(obiekt);

console.log(niezwiązanaFunkcja()); // undefined
console.log(związanaFunkcja()); // 42

W tym przykładzie niezwiązanaFunkcja traci kontekst, więc zwraca undefined, natomiast związanaFunkcja, dzięki użyciu bind, zachowuje kontekst obiektu obiekt.

Przekazywanie argumentów

Metody bind można również używać do przekazywania stałych argumentów do funkcji. To pozwala na tworzenie tzw. funkcji częściowo zastosowanych. Przykład:

function dodaj(a, b) {
    return a + b;
}

let dodajPięć = dodaj.bind(null, 5);
console.log(dodajPięć(10)); // 15

W tym przypadku funkcja dodajPięć jest wersją funkcji dodaj, która ma już przypisany pierwszy argument równy 5.

Użycie bind w callbackach i eventach

bind jest szczególnie użyteczny, gdy pracujemy z callbackami lub obsługą eventów, w których this często traci swój pierwotny kontekst. Przykład:

class Licznik {
    constructor() {
        this.liczba = 0;
    }

    dodaj() {
        this.liczba++;
        console.log(this.liczba);
    }
}

let licznik = new Licznik();
document.getElementById('przycisk').addEventListener('click', licznik.dodaj.bind(licznik));

W tym przypadku używamy bind do zapewnienia, że metoda dodaj obiektu licznik zachowa odpowiedni kontekst this podczas wywołania jako callback po kliknięciu przycisku.

Możliwe problemy z wykorzystaniem this

  • Zachowanie w funkcjach strzałkowychthis w funkcjach strzałkowych nie jest powiązane z kontekstem wywołania, ale z kontekstem leksykalnym, co może prowadzić do nieoczekiwanych wyników, jeśli nie jest to zrozumiałe dla programisty.
  • Utrata kontekstu. W callbackach lub przy przekazywaniu metod obiektu jako referencji, this może nie wskazywać na oczekiwany obiekt. Może to prowadzić do błędów wykonania.
  • Nadużywanie lub błędne użycie. Nieprawidłowe lub nadmierne używanie this może prowadzić do skomplikowania kodu i utrudnić jego zrozumienie i utrzymanie, zwłaszcza w większych projektach.
  • Jawne i niejawne zmiany kontekstu. Użycie metod callapply lub bind dla zmiany kontekstu this może wprowadzać zamieszanie co do tego, co jest aktualnie kontekstem wykonania, jeśli nie jest stosowane konsekwentnie i zrozumiale.

Ważne wskazówki

  • Zachowanie this może być skomplikowane i zależy od sposobu wywołania funkcji.
  • Funkcje strzałkowe eliminują wiele problemów związanych z niejednoznacznością this i są dobrym wyborem, gdy kontekst musi pozostać niezmieniony.
  • W nowoczesnym JavaScript często unika się tradycyjnych funkcji w rolach metod obiektu na rzecz funkcji strzałkowych, gdy potrzebne jest zachowanie kontekstu. 

METOD CHAINING: Możliwe jest wywołanie kilku metod na raz.


METODY GETTER i SETTER
Metody te maja za zadanie zarządzać pewnym stanem. Te metody używają słów kluczowych "get" i "set"
Są wywoływane jak właściwości ale wykonują kod. Wskaują na obiekty, jak w normalnych metodach.