Ten artykuł został pierwotnie napisany dla DigitalOcean.
słowo kluczowethis
jest bardzo ważnym pojęciem w JavaScript, a także szczególnie mylącym zarówno dla nowych programistów, jak i tych, którzy mają doświadczenie w innych językach programowania. W JavaScript this
jest odniesieniem do obiektu., Obiekt, do którego odnosi się this
, może się różnić, pośrednio w zależności od tego, czy jest globalny, w obiekcie, czy w konstruktorze, a także może się różnić bezpośrednio w zależności od użycia metod prototypowych bind
, call
, oraz apply
.
chociażthis
jest nieco skomplikowanym tematem, jest to również taki, który pojawia się zaraz po rozpoczęciu pisania pierwszych programów JavaScript., Niezależnie od tego, czy próbujesz uzyskać dostęp do elementu lub zdarzenia w modelu obiektowym dokumentu (DOM), budujesz klasy do pisania w stylu programowania obiektowego, czy używasz właściwości i metod zwykłych obiektów, napotkasz this
.
w tym artykule dowiesz się, co this
odnosi się do niejawnie w oparciu o kontekst, a także dowiesz się, jak używać metod bind
, call
I apply
do jawnego określ wartość this
.,
kontekst Niejawny
istnieją cztery główne konteksty, w których wartośćthis
może być domniemana:
- kontekst globalny
- jako metoda wewnątrz obiektu
- jako konstruktor funkcji lub Klasy
- jako Obsługa zdarzenia Dom
Globalny
w kontekście globalnym,this
odnosi się do obiektu globalnego. Gdy pracujesz w przeglądarce, kontekst Globalny to window
. Kiedy pracujesz w Node.js, globalny kontekst to global
.,
Uwaga: Jeśli nie znasz jeszcze pojęcia zakresu w JavaScript, zapoznaj się ze zrozumieniem zmiennych, zakresu i podnoszenia w JavaScript.
w przykładach możesz przećwiczyć kod w konsoli narzędzi programistycznych przeglądarki. Przeczytaj, Jak korzystać z konsoli programistów JavaScript, jeśli nie jesteś zaznajomiony z uruchomieniem kodu JavaScript w przeglądarce.
Jeśli zarejestrujesz wartość this
bez żadnego innego kodu, zobaczysz, do czego odnosi się obiekt this
.,
console.log(this)
Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
this
towindow
, który jest globalnym obiektem przeglądarki.
rozumiejąc zmienne, zakres i podnoszenie w JavaScript, nauczyłeś się, że funkcje mają swój własny kontekst dla zmiennych. Możesz pokusić się o stwierdzenie, że this
stosowałby te same zasady wewnątrz funkcji, ale tak nie jest. Funkcja najwyższego poziomu nadal zachowuje odniesieniethis
do obiektu globalnego.,
piszesz funkcję najwyższego poziomu lub funkcję, która nie jest powiązana z żadnym obiektem, jak to:
function printThis() { console.log(this)}printThis()
Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
nawet wewnątrz funkcji, this
odnosi się do window
lub obiektu globalnego.
jednak, gdy używasz trybu ścisłego, kontekstthis
w ramach funkcji w kontekście globalnym będzieundefined
.,
'use strict'function printThis() { console.log(this)}printThis()
undefined
ogólnie rzecz biorąc, bezpieczniej jest użyć trybu ścisłego, aby zmniejszyć prawdopodobieństwo wystąpienia nieoczekiwanego zakresuthis
. Rzadko ktoś chce odwołać się do obiektu window
używając this
.
aby uzyskać więcej informacji na temat trybu ścisłego i jakie zmiany wprowadza w odniesieniu do błędów i bezpieczeństwa, przeczytaj dokumentację trybu ścisłego na MDN.,
metoda obiektowa
metoda jest funkcją obiektu lub zadaniem, które obiekt może wykonać. Metoda używa this
w celu odniesienia się do Właściwości obiektu.
"The United States of America was founded in 1776."
w tym przykładziethis
jest taki sam jakamerica
.
w zagnieżdżonym obiekcie this
odnosi się do bieżącego zakresu obiektu metody. W poniższym przykładzie this.symbol
w obrębie details
obiekt odnosi się do details.symbol
.,
"The symbol is the eagle and the currency is USD."
innym sposobem myślenia o tym jest to, żethis
odnosi się do obiektu po lewej stronie kropki podczas wywoływania metody.
Konstruktor funkcji
gdy używasz słowa kluczowego new
, tworzy on instancję konstruktora funkcji lub klasy. Konstruktory funkcji były standardowym sposobem inicjalizacji obiektu zdefiniowanego przez użytkownika przed wprowadzeniem składni class
w aktualizacji ECMAScript 2015 Do JavaScript., W Understanding Classes in JavaScript dowiesz się, jak stworzyć konstruktor funkcji i równoważny konstruktor klasy.
"The United States of America was founded in 1776."
w tym kontekściethis
jest teraz powiązany z instancjąCountry
, która jest zawarta w stałejamerica
.
konstruktor klasy
konstruktor klasy działa tak samo jak konstruktor funkcji. Przeczytaj więcej o podobieństwach i różnicach między konstruktorami funkcji a klasami ES6 w zrozumieniu klas w JavaScript.,
this
wdescribe
metoda odnosi się do instancjiCountry
, która jestamerica
.
"The United States of America was founded in 1776."
Obsługa zdarzeń DOM
w przeglądarce znajduje się specjalny kontekstthis
dla obsługi zdarzeń. W programie obsługi zdarzeń wywołanym przez addEventListener
, this
będzie odnosić się do event.currentTarget
., Najczęściej programiści będą po prostu używać event.target
lub event.currentTarget
w razie potrzeby, aby uzyskać dostęp do elementów w DOM, ale ponieważthis
zmiany odniesienia w tym kontekście, ważne jest, aby wiedzieć.
w poniższym przykładzie utworzymy przycisk, dodamy do niego tekst i dodamy go do DOM. Gdy zarejestrujemy wartość this
wewnątrz procedury obsługi zdarzenia, wyświetli ona obiekt docelowy.,
<button>Click me</button>
gdy wkleisz to do swojej przeglądarki, zobaczysz przycisk dołączony do strony z napisem „Kliknij mnie”. Jeśli klikniesz przycisk, zobaczysz <button>Click me</button>
w konsoli, ponieważ kliknięcie przycisku rejestruje element, który jest samym przyciskiem. Dlatego, jak widzisz, this
odnosi się do elementu docelowego, do którego dodaliśmy detektor zdarzeń.,
jawny kontekst
we wszystkich poprzednich przykładach wartośćthis
była określona przez jej kontekst—czy jest globalny, w obiekcie, w skonstruowanej funkcji lub klasie, czy w obsłudze zdarzenia DOM. Jednak, używając call
, apply
lub bind
, możesz jednoznacznie określić, do czego odnosi się this
.,
trudno jest dokładnie określić, kiedy należy używać call
,apply
lubbind
, ponieważ będzie to zależało od kontekstu programu. bind
może być szczególnie pomocny, gdy chcesz użyć zdarzeń, aby uzyskać dostęp do właściwości jednej klasy w innej klasie. Na przykład, jeśli miałbyś napisać prostą grę, możesz oddzielić interfejs użytkownika i I / O w jedną klasę, A logikę i stan gry w inną., Ponieważ logika gry musiałaby mieć dostęp do danych wejściowych, takich jak naciśnięcie klawisza i kliknięcie, chcesz bind
zdarzenia, aby uzyskać dostęp do this
wartość klasy logiki gry.
ważną częścią jest wiedzieć, jak określić, do którego obiektu odnosi się this
, co można zrobić pośrednio z tym, czego nauczyłeś się w poprzednich sekcjach, lub bezpośrednio z trzema metodami, których nauczysz się następnie.,
wywołanie i zastosowanie
call
Iapply
są bardzo podobne—wywołują funkcję z podanym kontekstemthis
I opcjonalnymi argumentami. Jedyną różnicą pomiędzy call
I apply
jest to, że call
wymaga przekazywania argumentów jeden po drugim, a apply
pobiera argumenty jako tablicę.,
w tym przykładzie utworzymy obiekt i utworzymy funkcję, która odwołuje się dothis
ale nie mathis
kontekstu.
"undefined was written by undefined"
ponieważ summary
I book
nie mają połączenia, wywołanie summary
samo w sobie wydrukuje tylko undefined
, ponieważ szuka tych właściwości na obiekcie globalnym.,
Uwaga: próba tego w trybie ścisłym spowodowałaby
Uncaught TypeError: Cannot read property 'title' of undefined
, ponieważthis
sama byłabyundefined
.
jednak możesz użyć call
I apply
aby wywołać this
kontekst book
w funkcji.,
summary.call(book)// or:summary.apply(book)
"Brave New World was written by Aldous Huxley."
istnieje teraz połączenie pomiędzybook
Isummary
gdy te metody są stosowane. Potwierdźmy dokładnie, czym jest this
.
function printThis() { console.log(this)}printThis.call(book)// or:whatIsThis.apply(book)
{title: "Brave New World", author: "Aldous Huxley"}
w tym przypadkuthis
staje się obiektem przekazanym jako argument.
w ten sposóbcall
Iapply
są takie same, ale jest jedna mała różnica., Oprócz możliwości przekazania kontekstu this
jako pierwszego argumentu, możesz również przekazać dodatkowe argumenty.
function longerSummary(genre, year) { console.log( `${this.title} was written by ${this.author}. It is a ${genre} novel written in ${year}.`, )}
zcall
każda dodatkowa wartość, którą chcesz przekazać, jest wysyłana jako dodatkowy argument.,
longerSummary.call(book, 'dystopian', 1932)
"Brave New World was written by Aldous Huxley. It is a dystopian novel written in 1932."
Jeśli spróbujesz wysłać dokładnie te same argumenty za pomocą apply
, dzieje się tak:
longerSummary.apply(book, 'dystopian', 1932)
Uncaught TypeError: CreateListFromArrayLike called on non-object at <anonymous>:1:15
zamiast tego, dla apply
, musisz przekazać wszystkie argumenty w tablicy.
longerSummary.apply(book, )
"Brave New World was written by Aldous Huxley. It is a dystopian novel written in 1932."
różnica między przekazywaniem argumentów pojedynczo lub w tablicy jest subtelna, ale należy o tym pamiętać., Może być prostsze i wygodniejsze w użyciu apply
, ponieważ nie wymagałoby to zmiany wywołania funkcji, gdyby niektóre szczegóły parametrów uległy zmianie.
Bind
zarówno call
, jak i apply
są metodami jednorazowego użytku-jeśli wywołasz metodę z kontekstem this
, będzie ona miała tę funkcję, ale oryginalna funkcja pozostanie niezmieniona.,
czasami może być konieczne używanie metody w kółko z kontekstemthis
innego obiektu, a w takim przypadku można użyć metodybind
, aby utworzyć zupełnie nową funkcję z jawnie powiązanąthis
.
const braveNewWorldSummary = summary.bind(book)braveNewWorldSummary()
"Brave New World was written by Aldous Huxley"
w tym przykładzie za każdym razem, gdy wywołasz braveNewWorldSummary
, zawsze zwróci oryginalny this
wartość związana z nim., Próba przypisania do niej nowego kontekstu this
nie powiedzie się, więc zawsze możesz zaufać powiązanej funkcji, która zwróci oczekiwaną wartość this
.
chociaż ten przykład próbuje powiązaćbraveNewWorldSummary
po raz kolejny, zachowuje oryginalny kontekstthis
od momentu pierwszego związania.
funkcje strzałek
funkcje strzałek nie mają własnych this
Wiązanie. Zamiast tego, idą do następnego poziomu egzekucji.,
przydatne może być użycie funkcji strzałki w przypadkach, gdy naprawdę chceszthis
, aby odnieść się do zewnętrznego kontekstu. Na przykład, jeśli wewnątrz klasy znajduje się detektor zdarzeń, prawdopodobnie chcesz, aby this
odnosił się do pewnej wartości w klasie.
w tym przykładzie utworzysz i dodasz przycisk do DOM tak jak poprzednio, ale klasa będzie miała detektor zdarzeń, który zmieni wartość tekstową przycisku po kliknięciu.
Jeśli klikniesz przycisk, zawartość tekstowa zmieni się na wartośćbuttonText
., Jeśli nie użyłbyś tutaj funkcji strzałki, this
byłby równy event.currentTarget
I nie byłbyś w stanie użyć jej do uzyskania dostępu do wartości w klasie bez jej jawnego powiązania. Ta taktyka jest często używana na metodach klasowych w frameworkach takich jak React.
podsumowanie
w tym artykule dowiedzieliśmy się o this
w JavaScript i wielu różnych wartościach, które może mieć na podstawie niejawnego wiązania runtime i jawnego wiązania za pomocą bind
, call
I apply
., Dowiedzieliście się również, jak brak powiązania this
w funkcjach strzałek może być używany do odwoływania się do innego kontekstu. Dzięki tej wiedzy powinieneś być w stanie określić wartość this
w swoich programach.