this
stanowi fundament programowania zorientowanego obiektowo. Niestety, w przypadku JavaScript, jest jedną z najbardziej zagmatwanych części języka. Zarówno początkujący, jak i weterani innych języków programowania, będą mieli wiele okazji do złapania się za głowę. W przeciwieństwie do Javy i C#, wartość this
nie zawsze wiąże się z obiektem/funkcją zawierającą to słowo kluczowe.Wskaźnik this
w JavaScript
W JavaScript wiązanie this
jest zależne od kontekstu wywołania funkcji. Wyróżnia się pięć takich kontekstów: domyślny, niejawny, jawny, twardy, konstrukcyjny. Oczywiście może dojść do konfliktu kilku kontekstów, stąd musimy znać ich hierarchię. To nie wszystko, tryb restrykcyjny (strict mode) również ma istotny wpływ na działanie wskaźnika this
.
Jak widać, mamy do czynienia z nie lada szataństwem. Nie pozostało nam nic innego jak zarzucić na nie łańcuchy doświadczenia i zaciągnąć do pracy w naszym kodzie. Bez zrozumienia wszystkich wspomnianych mechanizmów nie będziemy w stanie poczynić postępów w programowaniu obiektowym. this
to absolutny fundament tego paradygmatu. Pozwala na zrezygnowanie z jawnego odwoływania się do obiektu. Stąd już krótka droga do wszechstronnych funkcji, które, bez dodatkowych modyfikacji, będą sobie radziły z różnymi parametrami.
Efektywna praca z this
w JavaScript wymaga znajomości trzech metod. Dzięki nim możemy w jawny sposób wskazać, z jaką wartością ma być związane this
. Wspomniane metody to: Function.prototype.call
, Function.prototype.apply
i Function.prototype.bind
.
Function.prototype.call
wywołuje funkcję z wartością this
wskazaną w pierwszym parametrze. Resztę parametrów, przekazywanych do wywoływanej funkcji, przyjmuje indywidualnie. Function.prototype.apply
, kuzyn call, ma takie samo działanie na this
, ale resztę parametrów przyjmuje jako tablicę.
Function.prototype.bind
zwraca nowy egzemplarz funkcji. Przy wywołaniu, wiązanie this
będzie trwale wskazywało na wartość, przekazaną podczas tworzenia funkcji.
var firstName = 'Mr. Window'; var hobby = 'Browsing the web with you'; function sayHi() { console.log(`Hello ${this.firstName}, your are into ${this.hobby}? That's great!`); } const marcin = { firstName: 'Marcin', age: 23, hobby: 'Weights lifting' } const sylwia = { firstName: 'Sylwia', gender: 'female', hobby: 'Reading books', } sayHi(); // Hello, window! sayHi.call(marcin); // Hello, Marcin! sayHi.call(sylwia); // Hello, Sylwia! const sayHiToMarcin = sayHi.bind(marcin); sayHiToMarcin(); // Hello, Marcin! sayHiToMarcin.call(sylwia); // Hello, Marcin!
Nie masz pojęcia co wydarzało się powyżej? Bez obaw. To właśnie dla Ciebie przygotowałem materiały źródłowe dostępne poniżej.
Materiały do nauki
- You Don’t Know JavaScript: this & Object Prototypes – Chapter I oraz Chapter II.
Spośród trzech książek z serii YDKJS, które przeczytałem do tej pory, ta dostarczyła mi najwięcej wartości. Pierwszy rozdział skupia się na rozjaśnieniu wszelkich wątpliwości co do tego, czym NIE JEST
this
w JS. W związku z zawiłościami, o których wspominałem wcześniej, taka negatywna definicja jest bardzo pomocna. Drugi rozdział można podzielić na dwie części. W pierwszej części przedstawione są wszystkie sposoby na utworzenie wiązaniathis
. W części drugiej poznasz wewnętrzną hierarchię obowiązującą pomiędzy tymi sposobami. Kyle przygotował kilka naprawdę ciekawych przykładów, w których bardzo łatwo błędnie ocenić, z jakim wiązaniem faktycznie mamy do czynienia. Wiele z nich często pojawia się na rozmowach kwalifikacyjnych. Warto znać. Warto rozumieć. Trud związany z przebrnięciem przez ten długi i stosunkowo wymagający materiał, z nawiązką wynagrodzą liczne przebłyski sygnalizujące wejście na wyższy poziom zrozumienia. Istny chaos związany z wskaźnikiemthis
powoli zacznie przyjmować znacznie przyjaźniejszą formę.Czas potrzebny na lekturę: 45 minut
- Bind and this – Object Creation in JavaScript.
Jako nagrodę za wytrwałość, przygotowałem dla Ciebie prezent. Są nim dwa odcinki wprost z mojego ulubionego kanału dotyczącego programowania – Fun Fun Function. MPJ ma niesamowity dar do tłumaczenia najbardziej skomplikowanych zagadnień w jasny i przejrzysty sposób.
- Gentle explanation of this keyword – Dmitri Pavlutin
Ostatni przygotowany przeze mnie materiał teoretyczny stanowi świetne uzupełnienie dla YDKJS. Wpis Dmyitra jest pełen estetycznych grafik obrazujących wszystko, nad czym Kyle Simpson rozwodził się w swojej książce. Ponadto, autor wskazuje najczęściej popełniane błędy i daje praktyczne rady, jak uniknąć ich w przyszłości.
Czas potrzebny na lekturę: 30 minut.
- Zadania praktyczne.
Jednym z dowodów na to, z jak trudnym zagadnieniem zmagamy się tym razem, jest deficyt ćwiczeń. Na wysokości zadania stanęła jedynie książka Eloquent JavaScript (w polskiej wersji: Zrozumieć JavaScript). Całość jest dostępna za darmo na stronie autora. Wykorzystaj zadania do rozdziału szóstego, aby przećwiczyć wiedzę nabytą z źródeł teoretycznych.
Zadania są wymagające. Nie poddawaj się. Trzymam kciuki!
Sprawdź się – lista pytań
Okej, na koniec mam dla Was listę pytań. Jeżeli uważnie zapoznaliście się z Materiałami do nauki, to nie powinno być problemów z udzieleniem poprawnych odpowiedzi.
- Co różni wskaźnik
this
w JS od tego występującego w innych językach programowania? - Od czego zależna jest wartość wskaźnika
this
? - Jaką wartość przyjmuje this podczas wywołania funkcji poprzez referencję w non-strict mode?
- Jaką wartość przyjmuje
this
podczas wywołania funkcji poprzez referencję w strict mode? - Jaką wartość przyjmuje
this
podczas wywołania metody za pomocą obiektu? - Czy wewnątrz funkcji zagnieżdżonej w metodzie obiektu, wskaźnik
this
posiada taką samą wartość, jak w zakresie otaczającym? Dlaczego? - Czy w JS mamy do czynienia z konstruktorami znanymi z innych języków programowania?
- Na co wskazuje
this
przy wywołaniu konstrukcyjnym funkcji z użyciem słowa kluczowegonew
? - Co stanie się jeżeli wywołamy konstrukcyjnie funkcję z pominięciem słowa kluczowego
new
? Na co będzie wskazywałothis
? - Co przekazujemy jako pierwszy parametr do metod
Function.prototype.call
iFunction.prototype.apply
? - Czym różnią się metody
Function.prototype.call
iFunction.prototype.apply
? - Z jakiej metody należy skorzystać, jeżeli zależy nam na wielokrotnym wywołaniu funkcji z określonym kontekstem?
- Co ma pierwszeństwo w razie konfliktu: bind czy call/apply?
- Na jakiej zasadzie dochodzi do wiązania
this
w funkcjach strzałkowych? - Jaka jest hierarchia wiązań
this
? - Jakie są zalety korzystania z
this
w porównaniu z bezpośrednim odwoływaniem się do obiektu?
Niczym ewangelista Anki, zachęcam do przekucia powyższych pytań w fiszki. W przypadku konieczności zapamiętania takiej ilości zasad i niuansów, ta metoda jest wyjątkowo skuteczna.