Zauważyłem, że wydaje się, że nie ma jasnego wyjaśnienia, czym this
jest słowo kluczowe i jak jest poprawnie (i niepoprawnie) używane w JavaScript w witrynie przepełnienia stosu.
Byłem świadkiem tego bardzo dziwnego zachowania i nie rozumiem, dlaczego tak się stało.
Jak this
działa i kiedy należy go używać?
javascript
this
Maxim Gerszkowicz
źródło
źródło
this
odradzathis
słowa kluczowego: rainsoft.io/gentle-explanation-of-this-in-javascriptOdpowiedzi:
Najpierw polecam przeczytanie artykułu Mike'a Westa Scope w JavaScript ( mirror ). Jest to doskonałe, przyjazne wprowadzenie do pojęć
this
i łańcuchów zasięgu w JavaScript.Kiedy zaczniesz się przyzwyczajać
this
, zasady są dość proste. Standard ECMAScript 5.1 definiujethis
:To powiązanie jest czymś, co interpreter JavaScript utrzymuje podczas oceny kodu JavaScript, podobnie jak specjalny rejestr procesora, który zawiera odniesienie do obiektu. Tłumacz interpretuje ThisBinding za każdym razem, gdy ustanawia kontekst wykonania w jednym z trzech różnych przypadków:
1. Wstępny globalny kontekst wykonania
Jest tak w przypadku kodu JavaScript, który jest oceniany na najwyższym poziomie, np. Gdy jest bezpośrednio w
<script>
:Podczas oceny kodu w początkowym globalnym kontekście wykonania ThisBinding jest ustawiany na obiekt globalny
window
( § 10.4.1.1 ).Wprowadzanie kodu ewaluacyjnego
… Przez bezpośrednie wywołanie
eval()
ThisBinding pozostaje niezmienione; jest to ta sama wartość, co ThisBinding kontekstu wykonania wywołania ( § 10.4.2 (2) (a)).… Jeśli nie przez bezpośrednie wywołanie
eval()
ThisBinding jest ustawiane na obiekt globalny, tak jakby było wykonywane w początkowym globalnym kontekście wykonania ( § 10.4.2 (1)).
§15.1.2.1.1 określa, do czego jest bezpośrednie połączenie
eval()
. Zasadniczoeval(...)
jest to połączenie bezpośrednie, podczas gdy coś takiego(0, eval)(...)
lubvar indirectEval = eval; indirectEval(...);
połączenie pośrednieeval()
. Zobacz odpowiedź chuckj w celu (1), eval ( 'To') vs eval ( 'To') w JavaScript? oraz szczegółowo ECMA-262-5 Dmitrija Soshnikova. Rozdział 2. Tryb ścisły. na kiedy możesz użyć połączenia pośredniegoeval()
.Wprowadzanie kodu funkcji
Dzieje się tak podczas wywoływania funkcji. Jeśli funkcja zostanie wywołana na obiekcie, takim jak in
obj.myMethod()
lub ekwiwalentobj["myMethod"]()
, wówczas ThisBinding zostanie ustawione na obiekt (obj
w przykładzie; § 13.2.1 ). W większości innych przypadków ThisBinding jest ustawiony na obiekt globalny ( § 10.4.3 ).Powodem pisania „w większości innych przypadków” jest to, że istnieje osiem wbudowanych funkcji ECMAScript 5, które umożliwiają określenie ThisBinding na liście argumentów. Te specjalne funkcje przyjmują tzw.
thisArg
ThisBinding podczas wywoływania funkcji ( § 10.4.3 ).Te specjalne wbudowane funkcje to:
Function.prototype.apply( thisArg, argArray )
Function.prototype.call( thisArg [ , arg1 [ , arg2, ... ] ] )
Function.prototype.bind( thisArg [ , arg1 [ , arg2, ... ] ] )
Array.prototype.every( callbackfn [ , thisArg ] )
Array.prototype.some( callbackfn [ , thisArg ] )
Array.prototype.forEach( callbackfn [ , thisArg ] )
Array.prototype.map( callbackfn [ , thisArg ] )
Array.prototype.filter( callbackfn [ , thisArg ] )
W przypadku
Function.prototype
funkcji są one wywoływane na obiekcie funkcji, ale zamiast ustawienia ThisBinding na obiekt funkcji, ThisBinding jest ustawiane nathisArg
.W przypadku
Array.prototype
funkcji podanacallbackfn
jest wywoływana w kontekście wykonania, w którym ThisBinding jest ustawione,thisArg
jeśli jest dostarczone; w przeciwnym razie do obiektu globalnego.Takie są reguły zwykłego JavaScript. Kiedy zaczynasz korzystać z bibliotek JavaScript (np. JQuery), może się okazać, że niektóre funkcje bibliotek manipulują wartością
this
. Twórcy tych bibliotek JavaScript robią to, ponieważ zazwyczaj obsługuje najczęściej spotykane przypadki użycia, a użytkownicy biblioteki zazwyczaj uważają to zachowanie za wygodniejsze. Przekazując funkcje zwrotne odnoszące sięthis
do funkcji bibliotecznych, należy zapoznać się z dokumentacją, aby uzyskać wszelkie gwarancje dotyczące wartościthis
wywołanej funkcji.Jeśli zastanawiasz się, w jaki sposób biblioteka JavaScript manipuluje wartością
this
, biblioteka po prostu używa jednej z wbudowanych funkcji JavaScript akceptującychthisArg
. Ty także możesz napisać własną funkcję, korzystając z funkcji zwrotnej ithisArg
:Jest szczególny przypadek, o którym jeszcze nie wspomniałem. Podczas konstruowania nowego obiektu za pośrednictwem
new
operatora interpreter JavaScript tworzy nowy, pusty obiekt, ustawia niektóre właściwości wewnętrzne, a następnie wywołuje funkcję konstruktora na nowym obiekcie. Zatem, gdy funkcja jest wywoływana w kontekście konstruktora, wartościąthis
jest nowy obiekt utworzony przez interpreter:Funkcje strzałek
Funkcje strzałek (wprowadzone w ECMA6) zmieniają zakres
this
. Zobacz istniejące pytanie kanoniczne, funkcja strzałki vs deklaracja / wyrażenie funkcji: czy są one równoważne / wymienne? po więcej informacji. Ale w skrócie:Dla zabawy sprawdź swoje zrozumienie na kilku przykładach
Aby wyświetlić odpowiedzi, najedź myszką na jasnoszare pola.
Jaka jest wartość
this
w zaznaczonej linii? Dlaczego?Jaka jest wartość
this
w zaznaczonej linii, gdyobj.staticFunction()
jest wykonywana? Dlaczego?Jaka jest wartość
this
w zaznaczonej linii? Dlaczego?Jaka jest wartość
this
w zaznaczonej linii? Dlaczego?Jaka jest wartość
this
w zaznaczonej linii? Dlaczego?źródło
setTimeout
przykład mathis
odwindow(global)
.Że
this
zachowuje się różnie w JavaScript słów kluczowych w porównaniu do innych języków. W językach zorientowanych obiektowothis
słowo kluczowe odnosi się do bieżącego wystąpienia klasy. W JavaScript wartośćthis
jest określona przez kontekst wywołania funkcji (context.function()
) i miejsce jej wywołania.1. W przypadku użycia w kontekście globalnym
Gdy używasz
this
w kontekście globalnym, jest on powiązany z obiektem globalnym (window
w przeglądarce)Gdy używasz
this
wewnątrz funkcji zdefiniowanej w kontekście globalnym,this
nadal jest powiązany z obiektem globalnym, ponieważ funkcja ta jest faktycznie metodą globalnego kontekstu.Powyżej
f1
jest metoda obiektu globalnego. W ten sposób możemy również wywołać go nawindow
obiekcie w następujący sposób:2. Przy zastosowaniu metody wewnątrz obiektu
Gdy używasz
this
słowa kluczowego w metodzie obiektowej,this
jest on związany z „bezpośrednim” otaczającym obiektem.Powyżej umieściłem słowo natychmiast w podwójnych cudzysłowach. Chodzi o to, aby po umieszczeniu obiektu w innym obiekcie
this
powiązać go z bezpośrednim rodzicem.Nawet jeśli funkcja zostanie jawnie dodana do obiektu jako metoda, nadal będzie on przestrzegać powyższych reguł, co
this
nadal wskazuje na bezpośredni obiekt nadrzędny.3. Podczas wywoływania funkcji bezkontekstowej
Gdy używasz
this
funkcji wewnętrznej, która jest wywoływana bez kontekstu (tj. Nie na żadnym obiekcie), jest ona powiązana z obiektem globalnym (window
w przeglądarce) (nawet jeśli funkcja jest zdefiniowana wewnątrz obiektu).Wypróbuj to wszystko z funkcjami
Możemy również wypróbować powyższe punkty za pomocą funkcji. Istnieją jednak pewne różnice.
this
. określić je.new
operatora.Poniżej wypróbowałem wszystkie rzeczy, które zrobiliśmy z Objectem i
this
wyżej, ale najpierw stworzyłem funkcję zamiast bezpośrednio pisać obiekt.4. W przypadku użycia wewnątrz funkcji konstruktora .
Gdy funkcja jest używana jako konstruktor (to znaczy, gdy jest wywoływana ze
new
słowem kluczowym),this
wnętrze funkcji wskazuje na budowany nowy obiekt.5. Przy zastosowaniu funkcji wewnętrznej zdefiniowanej w łańcuchu prototypów
Jeśli metoda znajduje się w łańcuchu prototypowym obiektu,
this
wewnątrz tej metody odnosi się do obiektu, do którego została wywołana metoda, tak jakby metoda została zdefiniowana na obiekcie.6. Wewnątrz funkcji call (), apply () i bind ()
Function.prototype
.this
która będzie używana podczas wykonywania funkcji. Przyjmują również wszelkie parametry, które mają zostać przekazane do oryginalnej funkcji, gdy jest ona wywoływana.fun.apply(obj1 [, argsArray])
Ustawiaobj1
jako wartośćthis
insidefun()
i wywołujefun()
przekazywanie elementówargsArray
jako argumentów.fun.call(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])
- Ustawiaobj1
jako wartośćthis
wewnątrzfun()
i wywołujefun()
przekazywaniearg1, arg2, arg3, ...
jako argumenty.fun.bind(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])
- Zwraca odniesienie do funkcjifun
zthis
wewnętrzną zabawą powiązaną zobj1
parametramifun
związanymi z określonymi parametramiarg1, arg2, arg3,...
.apply
,call
ibind
musiało stać się widoczne.apply
pozwala określić argumenty, które mają funkcjonować jako obiekt tablicowy, tj. obiekt zlength
właściwością liczbową i odpowiadającymi mu nieujemnymi liczbami całkowitymi.call
Pozwala natomiast na bezpośrednie podanie argumentów funkcji. Zarównoapply
icall
natychmiast wywołuje funkcję w określonym kontekście i przy użyciu określonych argumentów. Z drugiej stronybind
po prostu zwraca funkcję powiązaną z określonąthis
wartością i argumentami. Możemy przechwycić odwołanie do tej zwróconej funkcji, przypisując ją do zmiennej, a później możemy wywołać ją w dowolnym momencie.7.
this
wewnątrz procedur obsługi zdarzeńthis
bezpośrednio wewnątrz funkcji obsługi zdarzeń odnosi się do odpowiedniego elementu. Takie bezpośrednie przypisanie funkcji można wykonać przy użyciuaddeventListener
metody lub tradycyjnych metod rejestracji zdarzeń, takich jakonclick
.this
bezpośrednio wewnątrz właściwości zdarzenia (jak<button onclick="...this..." >
) elementu, odnosi się on do elementu.this
pośrednio przez inną funkcję wywoływaną wewnątrz funkcji obsługi zdarzenia lub właściwości zdarzenia odnosi się do obiektu globalnegowindow
.attachEvent
. Zamiast przypisywać funkcję do procedury obsługi zdarzeń (a tym samym tworząc metodę funkcji elementu), wywołuje funkcję zdarzenia (skutecznie wywołując ją w kontekście globalnym).Polecam lepiej wypróbować to w JSFiddle .
8.
this
w funkcji strzałki ES6W funkcji strzałki
this
zachowuje się jak zmienne wspólne: zostanie odziedziczony z zakresu leksykalnego. Funkcjathis
, w której zdefiniowano funkcję strzałki, będzie funkcją strzałkithis
.To jest to samo zachowanie, co:
Zobacz następujący kod:
źródło
this
nie jest ustawiana przez wywołanie. Ponieważ kod nie jest w trybie ścisłym, wartośćthis
musi zawsze być obiektem, więc domyślnie jest to obiekt globalny. I właśnie dlatego myślałem, że możemy bezpośrednio zadzwonićwindow.f1()
, więc oznaczaf1()
to , że środki są już dołączone dowindow
obiektu, to znaczy przed wywołaniem. Czy mylę się?window.fn
, co nie jest. to domyślnie globalnego obiektu, ponieważ nie ma odniesienia zasadę stosowane w zaproszeniu, nie z powodu których funkcja jest określona (tak to jest nadal ustawiony przez jaki funkcja została wywołana). Jeśli jawnie wywołujesz go za pomocąwindow.fn
, ustawiasz to na okno . Ten sam wynik, inny sposób postępowania. :-)Javascript's
this
Proste wywoływanie funkcji
Rozważ następującą funkcję:
Zauważ, że działamy w trybie normalnym, tzn. Tryb ścisły nie jest używany.
Podczas pracy w przeglądarce wartość
this
logowałaby się jakowindow
. Jest tak, ponieważwindow
jest to zmienna globalna w zakresie przeglądarki internetowej.Jeśli uruchomisz ten sam fragment kodu w środowisku takim jak node.js,
this
odsyłam do zmiennej globalnej w Twojej aplikacji.Teraz, jeśli uruchomimy to w trybie ścisłym, dodając instrukcję
"use strict";
na początku deklaracji funkcji,this
nie będzie już odwoływał się do zmiennej globalnej w żadnym ze środowisk. Odbywa się to w celu uniknięcia pomyłek w trybie ścisłym.this
w tym przypadku po prostu loguje sięundefined
, ponieważ tak właśnie jest, nie jest zdefiniowane.W poniższych przypadkach zobaczymy, jak manipulować wartością
this
.Wywołanie funkcji na obiekcie
Można to zrobić na różne sposoby. Jeśli wywołałeś metody rodzime w Javascripcie, takie jak
forEach
islice
, powinieneś już wiedzieć, żethis
zmienna w tym przypadku odnosi się doObject
wywołania tej funkcji (zwróć uwagę, że w javascript prawie wszystko jestObject
, w tymArray
s iFunction
s). Weźmy na przykład następujący kod.Jeśli an
Object
zawiera właściwość, która zawiera aFunction
, właściwość nazywa się metodą. Wywołana metoda zawsze będzie miałathis
zmienną ustawioną na tę, zObject
którą jest skojarzona. Dotyczy to zarówno trybów ścisłych, jak i nie ścisłych.Zauważ, że jeśli metoda jest przechowywana (a raczej kopiowana) w innej zmiennej, odwołanie do
this
nie jest już zachowywane w nowej zmiennej. Na przykład:Biorąc pod uwagę bardziej praktyczny scenariusz:
Słowo
new
kluczoweRozważ funkcję konstruktora w JavaScript:
Jak to działa? Zobaczmy, co się stanie, gdy użyjemy
new
słowa kluczowego.new
słowem kluczowym natychmiast zainicjujeObject
typPerson
.Object
ma ustawiony konstruktorPerson
. Pamiętaj też, żetypeof awal
wróciObject
tylko.Object
miałby przypisany prototypPerson.prototype
. Oznacza to, że każda metoda lub właściwość wPerson
prototypie będzie dostępna dla wszystkich instancjiPerson
, w tymawal
.Person
Wywoływana jest teraz sama funkcja ;this
będący odniesieniem do nowo zbudowanego obiektuawal
.Całkiem proste, co?
Zauważ, że oficjalna specyfikacja ECMAScript nigdzie nie stwierdza, że tego typu funkcje są
constructor
funkcjami rzeczywistymi . Są to po prostu normalne funkcje inew
można ich używać w dowolnej funkcji. Po prostu używamy ich jako takich, dlatego nazywamy je tylko takimi.Wywoływanie funkcji w funkcjach:
call
iapply
Więc tak, skoro
function
s też sąObjects
(i faktycznie zmiennymi pierwszej klasy w Javascript), nawet funkcje mają metody, które są ... no cóż, same w sobie.Wszystkie funkcje dziedziczą po globalnym
Function
, a dwie z jego wielu metod sącall
iapply
, i obie mogą być używane do manipulowania wartościąthis
funkcji, na której są wywoływane.Jest to typowy przykład użycia
call
. Zasadniczo przyjmuje pierwszy parametr i ustawiathis
funkcjęfoo
jako odniesieniethisArg
. Wszystkie pozostałe parametry przekazywanecall
są przekazywane do funkcjifoo
jako argumenty.Tak więc powyższy kod zaloguje się
{myObj: "is cool"}, [1, 2, 3]
do konsoli. Całkiem niezły sposób na zmianę wartościthis
dowolnej funkcji.apply
jest prawie taki sam, jakcall
zaakceptować, że przyjmuje tylko dwa parametry:thisArg
i tablicę zawierającą argumenty, które należy przekazać do funkcji. Tak więc powyższecall
wezwanie można przetłumaczyćapply
tak:Zauważ, że
call
iapply
może zastąpić wartośćthis
wywołania metody set metodą kropkową, którą omówiliśmy w drugim punkcie. Wystarczająco proste :)Prezentowanie ....
bind
!bind
jest bratemcall
iapply
. Jest to również metoda odziedziczona przez wszystkie funkcje z globalnegoFunction
konstruktora w Javascript. Różnica międzybind
icall
/apply
jest taka, że obacall
iapply
faktycznie wywołują funkcję.bind
Z drugiej strony, zwraca nową funkcję zthisArg
iarguments
pre-set. Weźmy przykład, aby lepiej to zrozumieć:Widzisz różnicę między tymi trzema? Jest subtelny, ale używa się go inaczej. Podobnie jak
call
iapply
,bind
również przewyższy wartośćthis
ustawioną przez wywołanie metodą kropkową.Zauważ też, że żadna z tych trzech funkcji nie zmienia żadnej z pierwotnych funkcji.
call
iapply
zwracałby wartość ze świeżo skonstruowanych funkcji whilebind
zwróci samą świeżo skonstruowaną funkcję, gotową do wywołania.Dodatkowe rzeczy, skopiuj to
Czasami nie podoba ci się fakt, że
this
zmienia się wraz z zasięgiem, zwłaszcza zasięgiem zagnieżdżonym. Spójrz na następujący przykład.W powyższym kodzie widzimy, że wartość
this
zmieniła się wraz z zagnieżdżonym zasięgiem, ale chcieliśmy wartościthis
z pierwotnego zakresu. Więc „skopiowane”this
dothat
i użyty zamiast kopiowaćthis
. Sprytnie, co?Indeks:
this
domyślnie przechowywane ?new
słowa kluczowego?this
pomocącall
iapply
?bind
.this
celu rozwiązania problemów związanych z zagnieżdżeniem.źródło
„to” dotyczy zakresu. Każda funkcja ma swój zakres, a ponieważ wszystko w JS jest obiektem, nawet funkcja może przechowywać w sobie pewne wartości za pomocą „this”. OOP 101 uczy, że „to” dotyczy tylko instancji obiektu. Dlatego za każdym razem, gdy funkcja jest wykonywana, nowa „instancja” tej funkcji ma nowe znaczenie „to”.
Większość ludzi jest zdezorientowana, gdy próbują użyć „tego” w funkcjach anonimowego zamknięcia, takich jak:
Więc tutaj, w każdym (), „to” nie zawiera „wartości”, której się spodziewasz (od
ponad tym). Aby rozwiązać ten problem (bez zamierzonej gry słów), programista może:Wypróbuj to; spodoba ci się ten wzór programowania
źródło
this
kluczowe nie ma nic wspólnego z zakresem. Ma to również znaczenie w funkcjach, które nie są właściwościami obiektów.this
nie chodzi wyłącznie o zakres. Chodzi o kontekst wykonania, który nie jest tym samym co zakres. JavaScript ma zasięg leksykalny (co oznacza, że zasięg jest określony przez lokalizację kodu), alethis
zależy od tego, w jaki sposób wywoływana jest funkcja, która go zawiera - a nie, gdzie jest ta funkcja.Odkąd ten wątek się podniósł, opracowałem kilka punktów dla czytelników, którzy nie znają
this
tematu.Jak określa się wartość
this
?Używamy tego w podobny sposób używamy zaimków w naturalnych języków takich jak angielski: „John pracuje szybko, ponieważ on próbuje złapać pociąg.” Zamiast tego moglibyśmy napisać „… John próbuje złapać pociąg”.
this
nie jest przypisywana wartość, dopóki obiekt nie wywoła funkcji, w której została zdefiniowana. W zakresie globalnym wszystkie zmienne globalne i funkcje są zdefiniowane nawindow
obiekcie. Dlategothis
w funkcji globalnej odnosi się do (i ma wartość)window
obiektu globalnego .Kiedy
use strict
,this
w globalnym iw anonimowych funkcji, które nie są zobowiązane do dowolnego obiektu posiada wartośćundefined
.Słowo
this
kluczowe jest najbardziej niezrozumiane, gdy: 1) pożyczamy metodę, która używathis
, 2) przypisujemy metodę, która używathis
zmiennej, 3) funkcja, która używathis
jest przekazywana jako funkcja zwrotna, i 4)this
jest używana wewnątrz zamknięcia - funkcja wewnętrzna. (2)Co trzyma przyszłość
Funkcje strzałki zdefiniowane w skrypcie ECMA 6 przejmują
this
powiązanie z zakresu obejmującego (funkcja lub globalny).Chociaż funkcje strzałek stanowią alternatywę dla używania
bind()
, ważne jest, aby pamiętać, że zasadniczo wyłączają tradycyjnythis
mechanizm na rzecz szerzej rozumianego zakresu leksykalnego. (1)Bibliografia:
źródło
this
w JavaScript zawsze odnosi się do „właściciela” funkcji, który jest aktualnie wykonywany .Jeśli nie zdefiniowano żadnego jawnego właściciela, wówczas odwołuje się do najwyższego właściciela, obiektu okna.
Więc gdybym to zrobił
element.onclick = someKindOfFunction;
this
odnosi się do obiektu elementu. Ale bądź ostrożny, wiele osób popełnia ten błąd.<element onclick="someKindOfFunction()">
W tym drugim przypadku odwołujesz się do funkcji, a nie do elementu. Dlatego
this
będzie odnosić się do obiektu okna.źródło
Każdy kontekst wykonania w javascript ma ten parametr ustawiany przez:
eval
Możesz ustawić wartość tego za pomocą
func.call
,func.apply
lubfunc.bind
.Domyślnie, co wprawia w zakłopotanie większość początkujących, gdy detektor jest wywoływany po wywołaniu zdarzenia na elemencie DOM, tą wartością funkcji jest element DOM.
jQuery sprawia, że zmiana tego trywialnego za pomocą jQuery.proxy jest łatwa.
źródło
this
w JavaScripcie mylące jest to, że nie jest to wewnętrzna właściwość samej funkcji, ale raczej artefakt sposobu jej wywoływania.func.call
,func.bind
itd. - Sushilthis
czy nie odwołać zakresu danej funkcji.this
będzie odnosić się do określonego obiektu (lub ewentualnieundefined
), który, jak powiedziałeś, można zmienić za pomocą.call()
lub.apply()
. Funkcją jest zakres jest (zasadniczo, gdy uproszczone), które zmienne ma dostęp, a to zależy wyłącznie od tego, gdzie funkcja jest zadeklarowana i nie mogą być zmieniane.this
a zakres nie ma nic wspólnego ze sobą w ES5 i wcześniej (np. Kiedy napisano tę odpowiedź). W ES2015 (aka ES6)this
i zakresu są związane jeden dość minimalny sposób WRT strzałka funkcje (Thethis
w funkcji strzałki jest dziedziczona z jej zakresu okalającego), alethis
nie odnosi się do zakresu.Tutaj jest dobrym źródłem
this
wJavaScript
.Oto podsumowanie:
globalnie to
W przeglądarce w zasięgu globalnym
this
jestwindow
obiektW
node
użyciu repl,this
jest top nazw. Możesz to nazwaćglobal
.Podczas
node
wykonywania ze skryptuthis
w zakresie globalnym zaczyna się jako pusty obiekt. To nie to samo coglobal
funkcja to
Z wyjątkiem przypadków obsługi zdarzeń DOM lub gdy
thisArg
podano (patrz niżej), zarówno w węźle, jak iw przeglądarce używającejthis
funkcji, która nie jest wywoływana znew
odniesieniami, zakres globalny…Jeśli skorzystasz
use strict;
, w takim przypadkuthis
będzieundefined
Jeśli wywołania funkcji z
new
tymthis
będzie nowym kontekście, nie będzie odwoływać się globalnythis
.Tworzone funkcje stają się obiektami funkcji. Automatycznie otrzymują specjalną
prototype
właściwość, do której można przypisać wartości. Po utworzeniu instancji przez wywołanie funkcjinew
masz dostęp do wartości przypisanych doprototype
właściwości. Dostęp do tych wartości uzyskuje się za pomocąthis
.Zazwyczaj błędem jest przypisywanie tablic lub obiektów do
prototype
. Jeśli chcesz, aby instancje miały własne tablice, utwórz je w funkcji, a nie w prototypie.Możesz użyć
this
w dowolnej funkcji obiektu, aby odnieść się do innych właściwości tego obiektu. To nie to samo, co instancja utworzona za pomocąnew
.W module obsługi zdarzeń DOM HTML
this
zawsze jest odwołanie do elementu DOM, do którego zostało dołączone zdarzenieChyba że
bind
kontekstWewnątrz atrybutów HTML, w których można umieścić JavaScript,
this
znajduje się odniesienie do elementu.Możesz użyć,
eval
aby uzyskać dostępthis
.Możesz użyć,
with
aby dodaćthis
do bieżącego zakresu, aby odczytywać i zapisywać wartościthis
bez odwoływania sięthis
wprost.jQuery w wielu miejscach będzie
this
odnosić się do elementu DOM.źródło
Daniel, niesamowite wyjaśnienie! Kilka słów na tej i dobrej liście
this
wskaźnika kontekstu wykonania w przypadku procedur obsługi zdarzeń.W dwóch słowach
this
w JavaScript wskazuje obiekt, od którego (lub z którego kontekstu wykonania) uruchomiono bieżącą funkcję i zawsze jest ona tylko do odczytu, i tak nie można jej ustawić (taka próba zakończy się błędem „Nieprawidłowa lewa ręka” komunikat „w zadaniu”.W przypadku procedur obsługi zdarzeń: wbudowane procedury obsługi zdarzeń, takie jak
<element onclick="foo">
, zastępują wszelkie inne procedury obsługi dołączone wcześniej i wcześniej, więc należy zachować ostrożność i lepiej w ogóle unikać delegowania funkcji inline. I dzięki Zara Alaverdyan, która zainspirowała mnie do tej listy przykładów poprzez debatę odrębną :)el.onclick = foo; // in the foo - obj
el.onclick = function () {this.style.color = '#fff';} // obj
el.onclick = function() {doSomething();} // In the doSomething - Window
el.addEventListener('click',foo,false) // in the foo - obj
el.attachEvent('onclick, function () { // this }') // window, all the compliance to IE :)
<button onclick="this.style.color = '#fff';"> // obj
<button onclick="foo"> // In the foo - window, but you can <button onclick="foo(this)">
źródło
Istnieje wiele nieporozumień dotyczących interpretacji „tego” słowa kluczowego w JavaScript. Mam nadzieję, że ten artykuł pozwoli wszystkim raz na zawsze odpocząć. I dużo więcej. Przeczytaj uważnie cały artykuł. Ostrzegam, że ten artykuł jest długi.
Niezależnie od kontekstu, w jakim jest używany, „to” zawsze odnosi się do „bieżącego obiektu” w JavaScript. Czym różni się „bieżący obiekt” w zależności od kontekstu . Kontekst może być dokładnie 1 z 6 poniższych sytuacji:
Poniżej opisano każdy z tych kontekstów jeden po drugim:
Kontekst globalny (tj. Poza wszystkimi funkcjami):
Poza wszystkimi funkcjami (tj. W kontekście globalnym) „bieżący obiekt” (a zatem wartość „tego” ) jest zawsze obiektem „okna” dla przeglądarek.
Wewnątrz bezpośredniego wywołania „funkcji niezwiązanej” :
W bezpośrednim wywołaniu funkcji „niezwiązanej” obiekt, który wywołał wywołanie funkcji, staje się „bieżącym obiektem” (a zatem wartością „tego” ). Jeśli funkcja jest wywoływana bez jawnego bieżącego obiektu , bieżącym obiektem jest albo obiekt „okna” (w trybie ścisłym) lub niezdefiniowany (w trybie ścisłym). Każda funkcja (lub zmienna) zdefiniowana w Global Context automatycznie staje się własnością obiektu „window”. Na przykład Załóżmy, że funkcja jest zdefiniowana w Global Context jako
staje się własnością obiektu okna, tak jakbyś go zdefiniował jako
W „Trybie ścisłym” Wywołanie / wywołanie tej funkcji bezpośrednio przez „UserDefinedFunction ()” automatycznie wywołuje / wywołuje ją jako „window.UserDefinedFunction ()„ tworząc ”okno jako „ bieżący obiekt ” (i stąd wartość „ this ” ) w ramach „ UserDefinedFunction ”. Wywołanie tej funkcji w„ Non Strict Mode ”spowoduje:
W „Strict Mode”, nazywając / Wywoływanie funkcji bezpośrednio poprzez „UserDefinedFunction ()” będzie „NIE” automatycznie zadzwoni / wywołać ją jako „window.UserDefinedFunction ()” .Hence „bieżący obiekt” (i wartość „to” ) w ramach „UserDefinedFunction” będzie niezdefiniowany . Wywołanie tej funkcji w „trybie ścisłym” spowoduje:
Jednak jawne wywołanie go przy użyciu obiektu okna spowoduje:
Spójrzmy na inny przykład. Proszę spojrzeć na następujący kod
W powyższym przykładzie widzimy, że gdy „UserDefinedFunction” została wywołana przez o1 , „to” przyjmuje wartość o1 i wyświetla się wartość jej właściwości „a” i „b” . Wartości „c” i „d” zostały pokazane jako niezdefiniowane, ponieważ o1 nie definiuje tych właściwości
Podobnie, gdy „UserDefinedFunction” została wywołana przez o2 , „to” przyjmuje wartość z O2 , a wartość jego właściwości „c” i „d” się displayed.The wartość „a” i „b” przedstawiono jako niezdefiniowane jako O2 czy nie definiuj tych właściwości.
Wewnątrz Pośrednie „niezwiązane funkcje” Wywołanie poprzez functionName.call i functionName.apply :
Kiedy „funkcja niezwiązana” jest wywoływana przez functionName.call lub functionName.apply , „bieżący obiekt” (i stąd wartość „this” ) jest ustawiany na wartość parametru „this” (pierwszy parametr) przekazywanego do wywołania / ubiegać się . Poniższy kod pokazuje to samo.
Powyższy kod wyraźnie pokazuje, że wartość „ta” dla dowolnej „funkcji niezwiązanej” może zostać zmieniona poprzez wywołanie / zastosowanie . Ponadto, jeśli parametr „ten” nie zostanie jawnie przekazany do wywołania / zastosowania , „bieżący obiekt” (a zatem wartość „tego”) zostanie ustawiona na „okno” w trybie Nieokreślonym i „niezdefiniowany” w trybie ścisłym.
Wewnątrz wywołania „Bound Function” (tj. Funkcja, która została powiązana przez wywołanie functionName.bind ):
Funkcja powiązana to funkcja, której wartość „ta” została naprawiona. Poniższy kod pokazał, jak działa „to” w przypadku funkcji powiązanej
Jak podano w powyższym kodzie, „tej” wartości dla dowolnej „funkcji powiązanej” NIE MOŻNA zmienić za pomocą wywołania / zastosowania . Ponadto, jeśli parametr „ten” nie zostanie jawnie przekazany do powiązania, „bieżący obiekt” (a zatem wartość „tego” ) zostanie ustawiona na „okno” w trybie Nieokreślone i „niezdefiniowany” w trybie ścisłym. Jeszcze jedna rzecz. Powiązanie już powiązanej funkcji nie zmienia wartości „this” . Pozostaje ustawiony jako wartość ustawiona przez pierwszą funkcję wiązania.
Podczas tworzenia obiektu poprzez „nowy” :
Wewnątrz funkcji konstruktora „bieżący obiekt” (i stąd wartość „tego” ) odnosi się do obiektu, który jest obecnie tworzony przez „nowy”, niezależnie od statusu powiązania funkcji. Jednak jeśli konstruktor jest funkcją powiązaną, zostanie wywołany z predefiniowanym zestawem argumentów ustawionym dla funkcji powiązanej.
Wewnątrz modułu obsługi zdarzeń Inline DOM :
Proszę spojrzeć na następujący fragment kodu HTML
„To” w Powyższe przykłady odnoszą się do „przycisku” elementu i „div” elementu odpowiednio.
W pierwszym przykładzie kolor czcionki przycisku powinien być ustawiony na biały po kliknięciu.
W drugim przykładzie, gdy kliknięty zostanie element „div” , powinien on wywołać funkcję OnDivClick z drugim parametrem odnoszącym się do klikniętego elementu div. Jednak wartość „this” w obrębie OnDivClick NIE MOŻE odnosić się do klikniętego elementu div . Powinien on być ustawiony jako „obiektu window” lub „nieokreślony” w Non ścisłych i Strict trybów odpowiednio (jeśli OnDivClick jest niezwiązany funkcja ) lub zestawu do predefiniowanej wartości stopniu (jeśli OnDivClick jest związany funkcja )
Poniżej podsumowano cały artykuł
W kontekście globalnym „to” zawsze odnosi się do „okna” obiektu
Za każdym razem, gdy wywoływana jest funkcja, wywoływana jest w kontekście obiektu ( „bieżący obiekt” ). Jeśli bieżący obiekt nie jest jawnie podany, bieżącym obiektem jest „obiekt okna” w trybie NIE STRIC i domyślnie „niezdefiniowany” w trybie Strict.
Wartość „this” w funkcji Non Bound to odwołanie do obiektu, w kontekście którego funkcja jest wywoływana ( „bieżący obiekt” )
Wartość „this” w funkcji Non Bound może zostać zastąpiona przez wywołanie i zastosowanie metod funkcji.
Wartość „this” jest stała dla funkcji Bound i nie może być zastąpiona przez wywołanie i zastosowanie metod funkcji.
Wiążąca i już powiązana funkcja nie zmienia wartości „this”. Pozostaje ustawiony jako wartość ustawiona przez pierwszą funkcję wiązania.
Wartość „this” w konstruktorze to obiekt, który jest tworzony i inicjowany
Wartość „this” w wbudowanym module obsługi zdarzeń DOM odnosi się do elementu, dla którego moduł obsługi zdarzeń jest podany.
źródło
Prawdopodobnie najbardziej szczegółowy i wyczerpujący artykuł
this
jest następujący:Delikatne objaśnienie „tego” słowa kluczowego w JavaScript
Chodzi o
this
to, aby zrozumieć, że typy wywoływania funkcji mają istotne znaczenie dla ustawieniathis
wartości.Kiedy kłopoty identyfikacji
this
, nie należy zadać sobie pytanie:ale nie należy zadać sobie pytanie:
W przypadku funkcji strzałki (szczególny przypadek przezroczystości kontekstu) zadaj sobie następujące pytanie:
Ten sposób myślenia jest prawidłowy, gdy
this
masz do czynienia z, i uratuje cię od bólu głowy.źródło
this
słowo kluczowe?Oto najlepsze wytłumaczenie, jakie widziałem: Zrozum to JavaScript z Clarity
Istnieją cztery scenariusze, w których może to być mylące:
Podaje przykłady kodu, wyjaśnienia i rozwiązania, które moim zdaniem były bardzo pomocne.
źródło
Mówiąc pseudoklasycznie, sposób, w jaki wiele wykładów uczy słowa kluczowego „this”, jest jak obiekt utworzony przez konstruktor klasy lub obiektu. Za każdym razem, gdy z klasy tworzony jest nowy obiekt, wyobraź sobie, że pod maską tworzona jest i zwracana lokalna instancja obiektu „tego”. Pamiętam, że uczyłem tak:
źródło
this
jest jedną z źle zrozumianych koncepcji w JavaScript, ponieważ zachowuje się nieco inaczej w zależności od miejsca. Po prostuthis
odnosi się do „właściciela” funkcji, którą obecnie wykonujemy .this
pomaga uzyskać bieżący obiekt (inaczej kontekst wykonania), z którym współpracujemy. Jeśli zrozumiesz, w którym obiekcie wykonywana jest bieżąca funkcja, możesz łatwo zrozumieć, cothis
to jest prądPowyżej tworzymy 3 zmienne o tej samej nazwie „val”. Jeden w kontekście globalnym, jeden wewnątrz obj, a drugi wewnątrz innerMethod obj. JavaScript rozpoznaje identyfikatory w określonym kontekście, przechodząc w górę łańcucha zasięgu od lokalnego go global.
Niewiele miejsc, w których
this
można różnicowaćWywołanie metody obiektu
Kiedy wiersz 1 jest wykonywany, JavaScript ustanawia kontekst wykonania (EC) dla wywołania funkcji, ustawiając
this
na obiekt , do którego odwołuje się to, co pojawiło się przed ostatnim „.” . więc w ostatnim wierszu możesz zrozumieć, żea()
został wykonany w kontekście globalnym, którym jestwindow
.Z konstruktorem
this
może służyć do odniesienia do tworzonego obiektuPo
Person()
wykonaniu nowego tworzony jest całkowicie nowy obiekt.Person
jest wywoływany, a jegothis
zestaw jest ustawiony tak, aby odwoływał się do tego nowego obiektu.Wywołanie funkcji
Jeśli przegapimy
new
słowo kluczowe,whatIsThis
odnosi się do najbardziej globalnego kontekstu, jaki może znaleźć (window
)Z modułami obsługi zdarzeń
Jeśli moduł obsługi zdarzeń jest wbudowany,
this
oznacza obiekt globalnyPodczas dodawania procedury obsługi zdarzeń za pomocą JavaScript
this
odnosi się do elementu DOM, który wygenerował zdarzenie..apply()
.call()
i.bind()
var that = this
znaczy w JavaScriptźródło
Wartość „this” zależy od „kontekstu”, w którym funkcja jest wykonywana. Kontekstem może być dowolny obiekt lub obiekt globalny, tj. Okno.
Semantyka „tego” różni się od tradycyjnych języków OOP. Powoduje to problemy: 1. gdy funkcja jest przekazywana do innej zmiennej (najprawdopodobniej wywołanie zwrotne); oraz 2. gdy zamknięcie jest wywoływane z metody członkowskiej klasy.
W obu przypadkach jest to ustawione na okno.
źródło
Czy to może pomóc? (Najbardziej nieporozumienie „tego” w javascript wynika z faktu, że zasadniczo nie jest ono powiązane z twoim obiektem, ale z bieżącym zakresem wykonywania - może nie tak dokładnie działa, ale zawsze wydaje mi się, że tak jest - zobacz artykuł, aby uzyskać pełne wyjaśnienie)
źródło
Trochę informacji na ten temat słowie kluczowym
Zalogujmy
this
słowo kluczowe do konsoli w zasięgu globalnym bez żadnego kodu, aleW kliencie / przeglądarce
this
słowo kluczowe jest globalnym obiektemwindow
i
W środowisku wykonawczym Server / Node / JavaScript
this
słowo kluczowe jest również obiektem globalnymmodule.exports
Pamiętaj,
exports
to tylko odniesienie domodule.exports
źródło
takie zastosowanie do Scope właśnie tak
wartość txt1 i txt jest taka sama w powyższym przykładzie $ (this) = $ ('# tbleName tbody tr') jest taki sam
źródło
Mam inne podejście
this
niż inne odpowiedzi, które, mam nadzieję, są pomocne.Jednym ze sposobów patrzenia na JavaScript jest sprawdzenie, że istnieje tylko jeden sposób na wywołanie funkcji 1 . To jest
Zawsze jest podana pewna wartość
objectForThis
.Cała reszta to cukier składniowy
functionObject.call
Tak więc wszystko inne można opisać przez to, jak się tłumaczy
functionObject.call
.Jeśli wywołujesz funkcję,
this
jest to „obiekt globalny”, który w przeglądarce jest oknemInnymi słowy,
został skutecznie przetłumaczony na
Pamiętaj, że jeśli użyjesz trybu ścisłego,
this
będzieundefined
co znaczy
Innymi słowy,
został skutecznie przetłumaczony na
W JavaScript istnieją operatorzy, jak
+
i-
i*
. Istnieje również operator kropki.
.
Operatora w przypadku korzystania z funkcji po prawej i po lewej obiektu skuteczne „oznacza obiekt jako przejściathis
funkcjonować.Przykład
Innymi słowy
bar.foo()
przekłada się naconst temp = bar.foo; temp.call(bar);
Zauważ, że nie ma znaczenia, jak funkcja została utworzona (głównie ...). Wszystkie przyniosą takie same wyniki
Ponownie wszystkie te są po prostu cukrem syntaktycznym
Kolejnym zmarszczkiem jest łańcuch prototypowy. Kiedy używasz
a.b
JavaScript, najpierw patrzy na obiekt, do którego odnosi się bezpośrednioa
właściwośćb
. Jeśli obiektb
nie zostanie znaleziony, JavaScript przeszuka prototyp obiektu, aby go znaleźćb
.Istnieją różne sposoby definiowania prototypu obiektu, najczęstszym w 2019 roku jest
class
słowo kluczowe. Dla celówthis
nie ma to jednak znaczenia. Liczy się to, że gdy szuka w obiekciea
właściwości,b
jeśli znajdzie właściwośćb
na obiekcie lub w swoim łańcuchu prototypów, jeślib
ostatecznie stanie się funkcją, wówczas obowiązują te same zasady, co powyżej.b
Odwołania do funkcji będą wywoływane przy użyciucall
metody i przekazywaniaa
jako objectForThis, jak pokazano na początku tej odpowiedzi.Teraz. Wyobraźmy sobie, że tworzymy funkcję, która jawnie ustawia się
this
przed wywołaniem innej funkcji, a następnie wywołuje ją za pomocą.
operatora (kropka)Po tłumaczenia do użycia
call
,obj.bar()
staje sięconst temp = obj.bar; temp.call(obj);
. Kiedy wchodzimy dobar
funkcji, wywołujemy,foo
ale jawnie przekazujemy inny obiekt dla obiektu objectForThis, więc kiedy dochodzimy do foothis
jest to wewnętrzny obiekt.To jest to, co oboje
bind
i=>
działa skutecznie zrobić. Są bardziej syntaktycznym cukrem. Skutecznie budują nową niewidzialną funkcję dokładnie tak, jakbar
powyżej, która ustawia jawniethis
przed wywołaniem dowolnej określonej funkcji. W przypadku powiązaniathis
jest ustawione na cokolwiek, co przekazujeszbind
.Zauważ, że gdyby
functionObject.bind
nie istniały, moglibyśmy stworzyć własny w ten sposóbi moglibyśmy to tak nazwać
Funkcje strzałek,
=>
operator to cukier syntaktyczny do wiązaniajest taki sam jak
Podobnie
bind
, tworzona jest nowa niewidzialna funkcja, która wywołuje daną funkcję z powiązaną wartością,objectForThis
ale w przeciwieństwiebind
do obiektu, który ma być związany, jest niejawna. Takthis
dzieje się, gdy=>
operator jest używany.Podobnie jak powyższe zasady
obj.foo()
tłumaczy, naconst temp = obj.foo; temp.call(obj);
co oznacza, że operator strzałki wewnątrzfoo
wiążeobj
się z nową niewidzialną funkcją i zwraca tę nową niewidzialną funkcję, do której jest przypisanab
.b()
będzie działać tak, jak zawsze ma,b.call(window)
lubb.call(undefined)
wywołuje nową, niewidoczną funkcję, która zostałafoo
utworzona. Ta niewidoczna funkcja ignorujethis
przekazane do niej i przechodziobj
jako objectForThis do funkcji strzałki.Powyższy kod tłumaczy się na
1
apply
to kolejna funkcja podobna docall
Ale od ES6 koncepcyjnie możesz to nawet przełożyć na
źródło
Podsumowanie
this
Javascript:this
zależy od sposobu, w jaki funkcja nie jest wywoływana, gdzie została utworzona!this
jest określana przez obiekt, który znajduje się po kropce. (window
w przestrzeni globalnej)this
odnosi się do elementu DOM, na którym wywołano zdarzenie.new
słowem kluczowym, wartośćthis
odnosi się do nowo utworzonego obiektuthis
z funkcjami:call
,apply
,bind
Przykład:
Przykładowe detektory zdarzeń:
Przykład konstruktora:
źródło
Aby właściwie to zrozumieć, trzeba zrozumieć kontekst, zakres i różnicę między nimi.
Zakres : w javascript zakres związany jest z widocznością zmiennych, zakres osiąga się poprzez użycie funkcji. (Przeczytaj więcej o zakresie)
Kontekst : Kontekst jest powiązany z obiektami. Odnosi się do obiektu, do którego należy funkcja. Kiedy używasz słowa kluczowego JavaScript „this”, odnosi się do obiektu, do którego należy funkcja. Na przykład wewnątrz funkcji, gdy mówisz: „this.accoutNumber”, masz na myśli właściwość „accoutNumber”, która należy do obiektu, do którego należy ta funkcja.
Jeśli obiekt „myObj” ma metodę o nazwie „getMyName”, to gdy słowo kluczowe „this” jest używane w „getMyName”, odnosi się do „myObj”. Jeśli funkcja „getMyName” została wykonana w zasięgu globalnym, wówczas „to” odnosi się do obiektu okna (z wyjątkiem trybu ścisłego).
Zobaczmy teraz przykład:
Uruchomienie powyższego kodu w wynikach przeglądarki:
Zgodnie z danymi wyjściowymi zawartymi w kontekście obiektu okna widać również, że prototyp okna odnosi się do obiektu.
Teraz spróbujmy wewnątrz funkcji:
Wynik:
Dane wyjściowe są takie same, ponieważ zarejestrowaliśmy zmienną „this” w zakresie globalnym i zarejestrowaliśmy ją w zakresie funkcjonalnym, nie zmieniliśmy kontekstu. W obu przypadkach kontekst był taki sam, związany z obiektem wdowy .
Teraz stwórzmy własny obiekt. W javascript możesz utworzyć obiekt na wiele sposobów.
Wynik:
Z powyższego przykładu wynika, że słowo kluczowe „to” odnosi się do nowego kontekstu związanego z myObj, a myObject ma również łańcuch prototypów do Object.
Rzućmy inny przykład:
wynik: czy ma sens, prawda? (czytaj komentarze)
Jeśli masz problem ze zrozumieniem powyższego przykładu, spróbujmy z naszym oddzwonieniem;
wynik:
Teraz zrozummy zakres, jaźń, IIFE i TO, jak się zachowuje
Wydajność jest niesamowita, prawda?
źródło
Prosta odpowiedź:
„to” słowo kluczowe zawsze zależy od kontekstu wywołania. Są one wymienione poniżej.
FUNKCJA JEST WYWOŁANA NOWYM SŁOWEM KLUCZOWYM
Jeśli funkcja zostanie wywołana ze słowem kluczowym NEW, TO zostanie przypisane do nowo utworzonego obiektu.
W powyższym będzie to związane z obiektem „myCar”
FUNKCJA JEST WYŁĄCZNIE WYKORZYSTANA Z WYKORZYSTANIEM POŁĄCZEŃ I STOSOWANIA.
W takim przypadku TO zostanie powiązane z obiektem, który jest jawnie przekazany do funkcji.
JEŻELI FUNKCJA JEST BEZWZGLĘDNIE OBOWIĄZKOWA, NINIEJSZYM BĘDZIE ZWIĄZANY Z TYM OBIEKTEM
JEŻELI FUNKCJA JEST WYWOŁANA BEZ ŻADNEGO KONTEKSTU, NINIEJSZYM BĘDZIE ZWIĄZANA Z GLOBALNYM OBIEKTEM
W TRYBIE ŚCISŁOŚCI BĘDZIE NIE DANE
źródło