Jak działa słowo kluczowe „to”?
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 Stack Overflow.
Byłem z nim świadkiem bardzo dziwnego zachowania i nie mogłem zrozumieć, dlaczego tak się stało.
Jak this
działa i kiedy należy go używać?
Odpowiedzi
Polecam najpierw przeczytać artykuł Mike'a Westa Scope in JavaScript ( mirror ). Jest to doskonałe, przyjazne wprowadzenie do koncepcji this
i łańcuchów zasięgu w JavaScript.
Kiedy zaczniesz się przyzwyczaić this
, zasady są w rzeczywistości dość proste. Standard ECMAScript 5.1 definiuje this
:
§11.1.1
this
kluczoweDo
this
ocenia słowo kluczowe aby wartości ThisBinding bieżącego kontekstu wykonania
ThisBinding jest czymś, co interpreter JavaScript zachowuje podczas oceny kodu JavaScript, na przykład specjalny rejestr procesora, który przechowuje odniesienie do obiektu. Interpreter aktualizuje ThisBinding za każdym razem, gdy ustanawia kontekst wykonania w jednym z tylko trzech różnych przypadków:
1. Początkowy globalny kontekst wykonania
Tak jest w przypadku kodu JavaScript, który jest oceniany na najwyższym poziomie, np. Bezpośrednio w <script>
:
<script>
alert("I'm evaluated in the initial global execution context!");
setTimeout(function () {
alert("I'm NOT evaluated in the initial global execution context.");
}, 1);
</script>
Podczas oceny kodu w początkowym kontekście wykonania globalnego ThisBinding jest ustawiana na obiekt globalny window
( §10.4.1.1 ).
2. Wprowadzenie kodu ewaluacyjnego
… Przez bezpośrednie wywołanie
eval()
ThisBinding pozostaje niezmienione; jest taka sama jak wartość ThisBinding kontekstu wykonania wywołującego ( §10.4.2 (2) (a)).… Jeśli nie przez bezpośrednie wywołanie
eval()
ThisBinding jest ustawiane na obiekt globalny, tak jakby był wykonywany w początkowym globalnym kontekście wykonania ( §10.4.2 (1)).
W §15.1.2.1.1 określono, czym jest bezpośrednie połączenie eval()
. Zasadniczo eval(...)
jest to wezwanie bezpośrednie, podczas gdy coś w rodzaju (0, eval)(...)
lub var indirectEval = eval; indirectEval(...);
jest wezwaniem pośrednim eval()
. Zobacz odpowiedź chuckj w celu (1), eval ( 'To') vs eval ( 'To') w JavaScript? oraz szczegółowo ECMA-262-5 Dmitrija Sosznikowa. Rozdział 2. Tryb ścisły. kiedy możesz skorzystać z eval()
połączenia pośredniego .
3. Wprowadzenie kodu funkcji
Dzieje się tak podczas wywoływania funkcji. Jeśli funkcja jest wywoływana na obiekcie, takim jak in obj.myMethod()
lub równoważny obj["myMethod"]()
, to ThisBinding jest ustawiana 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 napisania „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 funkcje specjalne przyjmują tak zwaną wartość, thisArg
która staje się 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 w obiekcie funkcji, ale zamiast ustawiać ThisBinding na obiekt funkcji, ThisBinding jest ustawiana na thisArg
.
W przypadku Array.prototype
funkcji dana callbackfn
jest wywoływana w kontekście wykonywania, w którym wartość ThisBinding jest ustawiona na, thisArg
jeśli została podana ; w przeciwnym razie do obiektu globalnego.
Takie są zasady dla zwykłego JavaScript. Rozpoczynając korzystanie z bibliotek JavaScript (np. JQuery), może się okazać, że pewne funkcje biblioteczne manipulują wartością this
. Twórcy tych bibliotek JavaScript robią to, ponieważ zwykle obsługują one najczęstsze przypadki użycia, a użytkownicy biblioteki zazwyczaj uważają to zachowanie za wygodniejsze. Podczas przekazywania funkcji zwrotnych odwołujących się this
do funkcji bibliotecznych należy zapoznać się z dokumentacją, aby uzyskać wszelkie gwarancje dotyczące tego, jaka jest wartość, this
gdy funkcja jest wywoływana.
Jeśli zastanawiasz się, w jaki sposób biblioteka JavaScript manipuluje wartością elementu this
, biblioteka po prostu używa jednej z wbudowanych funkcji JavaScript akceptujących rozszerzenie thisArg
. Ty też możesz napisać swoją własną funkcję, przyjmującą funkcję zwrotną i thisArg
:
function doWork(callbackfn, thisArg) {
//...
if (callbackfn != null) callbackfn.call(thisArg);
}
Jest specjalny przypadek, o którym jeszcze nie wspomniałem. Podczas konstruowania nowego obiektu za pośrednictwem new
operatora interpreter JavaScript tworzy nowy, pusty obiekt, ustawia pewne właściwości wewnętrzne, a następnie wywołuje funkcję konstruktora na nowym obiekcie. Tak więc, gdy funkcja jest wywoływana w kontekście konstruktora, wartością this
jest nowy obiekt, który utworzył interpreter:
function MyType() {
this.someData = "a string";
}
var instance = new MyType();
// Kind of like the following, but there are more steps involved:
// var instance = {};
// MyType.call(instance);
Funkcje strzałek
Funkcje strzałek (wprowadzone w ECMA6) zmieniają zakres this
. Zobacz istniejące pytanie kanoniczne, funkcja strzałki a deklaracja / wyrażenia funkcji: Czy są one równoważne / wymienne? po więcej informacji. Ale w skrócie:
Funkcje strzałkowe nie mają własnego
this
.... powiązania. Zamiast tego te identyfikatory są rozwiązywane w zakresie leksykalnym, jak każda inna zmienna. Oznacza to, że wewnątrz funkcji strzałkowejthis
... odwołuje się (s) do wartościthis
środowiska, w którym funkcja strzałkowa jest zdefiniowana.
Dla zabawy sprawdź swoje zrozumienie, podając kilka przykładów
Aby odsłonić odpowiedzi, najedź myszką na jasnoszare pola.
- Jaka jest wartość
this
w zaznaczonej linii? Dlaczego?
window
- Zaznaczona linia jest oceniana w początkowym globalnym kontekście wykonania.
if (true) {
// What is `this` here?
}
- Jaka jest wartość
this
w zaznaczonej linii, kiedyobj.staticFunction()
jest wykonywana? Dlaczego?
obj
- Podczas wywoływania funkcji na obiekcie ThisBinding jest ustawiana na obiekt.
var obj = {
someData: "a string"
};
function myFun() {
return this // What is `this` here?
}
obj.staticFunction = myFun;
console.log("this is window:", obj.staticFunction() == window);
console.log("this is obj:", obj.staticFunction() == obj);
- Jaka jest wartość
this
w zaznaczonej linii? Dlaczego?
window
W tym przykładzie interpreter JavaScript wprowadza kod funkcji, ale ponieważ
myFun
/obj.myMethod
nie jest wywoływana w obiekcie, wartość ThisBinding jest ustawiona nawindow
.Różni się to od Pythona, w którym dostęp do metody method (
obj.myMethod
) tworzy powiązany obiekt metody .
var obj = {
myMethod: function () {
return this; // What is `this` here?
}
};
var myFun = obj.myMethod;
console.log("this is window:", myFun() == window);
console.log("this is obj:", myFun() == obj);
- Jaka jest wartość
this
w zaznaczonej linii? Dlaczego?
window
Ten był trudny. Podczas oceny kodu eval,
this
jestobj
. Jednak w kodzie evalmyFun
nie jest wywoływana na obiekcie, więc ThisBinding jest ustawiona nawindow
dla wywołania.
<!-- no snippet because, seemingly, eval doesn’t work in snippets -->
function myFun() {
return this; // What is `this` here?
}
var obj = {
myMethod: function () {
eval("myFun()");
}
};
- Jaka jest wartość
this
w zaznaczonej linii? Dlaczego?
obj
Linia
myFun.call(obj);
wywołuje specjalną wbudowaną funkcjęFunction.prototype.call()
, która przyjmujethisArg
jako pierwszy argument.
function myFun() {
return this; // What is `this` here?
}
var obj = {
someData: "a string"
};
console.log("this is window:", myFun.call(obj) == window);
console.log("this is obj:", myFun.call(obj) == obj);
Że this
zachowuje się różnie w JavaScript słów kluczowych w porównaniu do innych języków. W językach zorientowanych obiektowo this
słowo kluczowe odnosi się do bieżącej instancji klasy. W JavaScript wartość funkcji this
jest określana przez kontekst wywołania funkcji function ( context.function()
) i miejsce jej wywołania.
1. Używane w kontekście globalnym
Kiedy używasz this
w kontekście globalnym, jest on powiązany z obiektem globalnym ( window
w przeglądarce)
document.write(this); //[object Window]
Kiedy używasz this
wewnątrz funkcji zdefiniowanej w kontekście globalnym, this
jest nadal powiązany z obiektem globalnym, ponieważ funkcja jest w rzeczywistości metodą kontekstu globalnego.
function f1()
{
return this;
}
document.write(f1()); //[object Window]
Powyżej f1
jest wykonana metoda obiektu globalnego. Zatem możemy to również wywołać na window
obiekcie w następujący sposób:
function f()
{
return this;
}
document.write(window.f()); //[object Window]
2. W przypadku użycia wewnątrz metody obiektowej
Kiedy używasz this
słowa kluczowego wewnątrz metody obiektu, this
jest powiązany z "bezpośrednim" otaczającym obiektem.
var obj = {
name: "obj",
f: function () {
return this + ":" + this.name;
}
};
document.write(obj.f()); //[object Object]:obj
Powyżej umieściłem słowo natychmiast w podwójnych cudzysłowach. Chodzi o to, aby zwrócić uwagę, że jeśli zagnieździsz obiekt w innym obiekcie, this
zostanie on powiązany z bezpośrednim rodzicem.
var obj = {
name: "obj1",
nestedobj: {
name:"nestedobj",
f: function () {
return this + ":" + this.name;
}
}
}
document.write(obj.nestedobj.f()); //[object Object]:nestedobj
Nawet jeśli dodasz funkcję jawnie do obiektu jako metodę, nadal będzie ona przestrzegać powyższych reguł, czyli this
nadal wskazuje na bezpośredni obiekt nadrzędny.
var obj1 = {
name: "obj1",
}
function returnName() {
return this + ":" + this.name;
}
obj1.f = returnName; //add method to object
document.write(obj1.f()); //[object Object]:obj1
3. Podczas wywoływania funkcji bezkontekstowej
Kiedy 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).
var context = "global";
var obj = {
context: "object",
method: function () {
function f() {
var context = "function";
return this + ":" +this.context;
};
return f(); //invoked without context
}
};
document.write(obj.method()); //[object Window]:global
Wypróbuj wszystko z funkcjami
Możemy wypróbować powyższe punkty również z funkcjami. Istnieją jednak pewne różnice.
- Powyżej dodaliśmy składowe do obiektów przy użyciu notacji literału obiektowego. Możemy dodawać członków do funkcji za pomocą
this
. aby je określić. - Notacja dosłowna obiektu tworzy instancję obiektu, której możemy natychmiast użyć. W przypadku funkcji może być konieczne najpierw utworzenie jej instancji za pomocą
new
operatora. - Również w podejściu literału obiektowego możemy jawnie dodawać składowe do już zdefiniowanego obiektu za pomocą operatora kropki. Jest to dodawane tylko do określonej instancji. Jednak dodałem zmienną do prototypu funkcji, aby była ona odzwierciedlana we wszystkich wystąpieniach funkcji.
Poniżej wypróbowałem wszystkie rzeczy, które zrobiliśmy z Object i nowszymi this
wersjami, ale najpierw tworzyłem funkcję zamiast bezpośrednio pisać obiekt.
/*********************************************************************
1. When you add variable to the function using this keyword, it
gets added to the function prototype, thus allowing all function
instances to have their own copy of the variables added.
*********************************************************************/
function functionDef()
{
this.name = "ObjDefinition";
this.getName = function(){
return this+":"+this.name;
}
}
obj1 = new functionDef();
document.write(obj1.getName() + "<br />"); //[object Object]:ObjDefinition
/*********************************************************************
2. Members explicitly added to the function protorype also behave
as above: all function instances have their own copy of the
variable added.
*********************************************************************/
functionDef.prototype.version = 1;
functionDef.prototype.getVersion = function(){
return "v"+this.version; //see how this.version refers to the
//version variable added through
//prototype
}
document.write(obj1.getVersion() + "<br />"); //v1
/*********************************************************************
3. Illustrating that the function variables added by both above
ways have their own copies across function instances
*********************************************************************/
functionDef.prototype.incrementVersion = function(){
this.version = this.version + 1;
}
var obj2 = new functionDef();
document.write(obj2.getVersion() + "<br />"); //v1
obj2.incrementVersion(); //incrementing version in obj2
//does not affect obj1 version
document.write(obj2.getVersion() + "<br />"); //v2
document.write(obj1.getVersion() + "<br />"); //v1
/*********************************************************************
4. `this` keyword refers to the immediate parent object. If you
nest the object through function prototype, then `this` inside
object refers to the nested object not the function instance
*********************************************************************/
functionDef.prototype.nestedObj = { name: 'nestedObj',
getName1 : function(){
return this+":"+this.name;
}
};
document.write(obj2.nestedObj.getName1() + "<br />"); //[object Object]:nestedObj
/*********************************************************************
5. If the method is on an object's prototype chain, `this` refers
to the object the method was called on, as if the method was on
the object.
*********************************************************************/
var ProtoObj = { fun: function () { return this.a } };
var obj3 = Object.create(ProtoObj); //creating an object setting ProtoObj
//as its prototype
obj3.a = 999; //adding instance member to obj3
document.write(obj3.fun()+"<br />");//999
//calling obj3.fun() makes
//ProtoObj.fun() to access obj3.a as
//if fun() is defined on obj3
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
wewnątrz ciała funkcji wskazuje na nowo konstruowany obiekt.
var myname = "global context";
function SimpleFun()
{
this.myname = "simple function";
}
var obj1 = new SimpleFun(); //adds myname to obj1
//1. `new` causes `this` inside the SimpleFun() to point to the
// object being constructed thus adding any member
// created inside SimipleFun() using this.membername to the
// object being constructed
//2. And by default `new` makes function to return newly
// constructed object if no explicit return value is specified
document.write(obj1.myname); //simple function
5. W przypadku użycia wewnątrz funkcji zdefiniowanej w łańcuchu prototypów
Jeśli metoda znajduje się w łańcuchu prototypów obiektu, this
wewnątrz takiej metody odwołuje się do obiektu, na którym metoda została wywołana, tak jakby metoda została zdefiniowana na obiekcie.
var ProtoObj = {
fun: function () {
return this.a;
}
};
//Object.create() creates object with ProtoObj as its
//prototype and assigns it to obj3, thus making fun()
//to be the method on its prototype chain
var obj3 = Object.create(ProtoObj);
obj3.a = 999;
document.write(obj3.fun()); //999
//Notice that fun() is defined on obj3's prototype but
//`this.a` inside fun() retrieves obj3.a
6. Funkcje wewnętrzne call (), apply () i bind ()
- Wszystkie te metody są zdefiniowane w
Function.prototype
. - Te metody pozwalają na jednorazowe napisanie funkcji i wywołanie jej w innym kontekście. Innymi słowy, pozwalają określić,
this
jaka wartość zostanie użyta podczas wykonywania funkcji. Pobierają również wszelkie parametry, które mają być 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 argumenty.fun.call(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])
- Ustawiaobj1
wartośćthis
insidefun()
i wywołujefun()
przekazaniearg1, arg2, arg3, ...
jako jej argumenty.fun.bind(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])
- Zwraca odniesienie do funkcjifun
zthis
wewnętrzną zabawą powiązanąobj1
i parametramifun
powiązania z określonymi parametramiarg1, arg2, arg3,...
.- Do tej pory różnica między
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ą numeryczną i odpowiadającymi jej właściwościami nieujemnych liczb całkowitych. Natomiastcall
pozwala bezpośrednio określić argumenty funkcji. Zarównoapply
icall
natychmiast wywołuje funkcję w określonym kontekście iz określonymi argumentami. Z drugiej stronybind
po prostu zwraca funkcję powiązaną z określonąthis
wartością i argumentami. Możemy przechwycić odniesienie do tej zwróconej funkcji, przypisując ją do zmiennej, a później możemy ją wywołać w dowolnym momencie.
function add(inc1, inc2)
{
return this.a + inc1 + inc2;
}
var o = { a : 4 };
document.write(add.call(o, 5, 6)+"<br />"); //15
//above add.call(o,5,6) sets `this` inside
//add() to `o` and calls add() resulting:
// this.a + inc1 + inc2 =
// `o.a` i.e. 4 + 5 + 6 = 15
document.write(add.apply(o, [5, 6]) + "<br />"); //15
// `o.a` i.e. 4 + 5 + 6 = 15
var g = add.bind(o, 5, 6); //g: `o.a` i.e. 4 + 5 + 6
document.write(g()+"<br />"); //15
var h = add.bind(o, 5); //h: `o.a` i.e. 4 + 5 + ?
document.write(h(6) + "<br />"); //15
// 4 + 5 + 6 = 15
document.write(h() + "<br />"); //NaN
//no parameter is passed to h()
//thus inc2 inside add() is `undefined`
//4 + 5 + undefined = NaN</code>
7. this
wewnętrzne programy obsługi zdarzeń
- Kiedy przypisujesz funkcję bezpośrednio do programów obsługi zdarzeń elementu, użycie
this
bezpośrednio wewnątrz funkcji obsługi zdarzeń odnosi się do odpowiedniego elementu. Takie bezpośrednie przypisanie funkcji można wykonaćaddeventListener
metodą lub tradycyjnymi metodami rejestracji zdarzeń, takimi jakonclick
. - Podobnie, gdy używasz
this
bezpośrednio wewnątrz właściwości zdarzenia (np.<button onclick="...this..." >
) Elementu, odwołuje się do elementu. - Jednak użycie
this
pośrednio przez inną funkcję wywoływaną wewnątrz funkcji obsługi zdarzenia lub właściwości zdarzenia jest rozpoznawane jako obiekt globalnywindow
. - To samo powyższe zachowanie uzyskuje się, gdy dołączymy funkcję do modułu obsługi zdarzeń za pomocą metody modelu rejestracji zdarzeń firmy Microsoft
attachEvent
. Zamiast przypisywać funkcję do obsługi zdarzenia (i tym samym tworzyć metodę funkcji elementu), wywołuje funkcję na zdarzeniu (efektywnie wywołując ją w kontekście globalnym).
Polecam lepiej spróbować tego w JSFiddle .
<script>
function clickedMe() {
alert(this + " : " + this.tagName + " : " + this.id);
}
document.getElementById("button1").addEventListener("click", clickedMe, false);
document.getElementById("button2").onclick = clickedMe;
document.getElementById("button5").attachEvent('onclick', clickedMe);
</script>
<h3>Using `this` "directly" inside event handler or event property</h3>
<button id="button1">click() "assigned" using addEventListner() </button><br />
<button id="button2">click() "assigned" using click() </button><br />
<button id="button3" onclick="alert(this+ ' : ' + this.tagName + ' : ' + this.id);">used `this` directly in click event property</button>
<h3>Using `this` "indirectly" inside event handler or event property</h3>
<button onclick="alert((function(){return this + ' : ' + this.tagName + ' : ' + this.id;})());">`this` used indirectly, inside function <br /> defined & called inside event property</button><br />
<button id="button4" onclick="clickedMe()">`this` used indirectly, inside function <br /> called inside event property</button> <br />
IE only: <button id="button5">click() "attached" using attachEvent() </button>
8. this
w funkcji strzałek ES6
W funkcji strzałkowej this
zachowuje się jak zwykłe zmienne: zostanie odziedziczona ze swojego zakresu leksykalnego. Funkcja this
, w której zdefiniowano funkcję strzałkową, będzie funkcją strzałkową this
.
To jest to samo zachowanie, co:
(function(){}).bind(this)
Zobacz poniższy kod:
const globalArrowFunction = () => {
return this;
};
console.log(globalArrowFunction()); //window
const contextObject = {
method1: () => {return this},
method2: function(){
return () => {return this};
}
};
console.log(contextObject.method1()); //window
const contextLessFunction = contextObject.method1;
console.log(contextLessFunction()); //window
console.log(contextObject.method2()()) //contextObject
const innerArrowFunction = contextObject.method2();
console.log(innerArrowFunction()); //contextObject
JavaScript this
Proste wywołanie funkcji
Rozważ następującą funkcję:
function foo() {
console.log("bar");
console.log(this);
}
foo(); // calling the function
Zauważ, że uruchamiamy to w trybie normalnym, tj. Tryb ścisły nie jest używany.
Podczas uruchamiania w przeglądarce wartość this
byłaby rejestrowana jako window
. Dzieje się 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
odniesie się 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ż odnosić się do zmiennej globalnej w żadnym ze środowisk. Ma to na celu uniknięcie nieporozumień w trybie ścisłym. this
w tym przypadku wystarczy zalogować undefined
, ponieważ tak właśnie jest, nie jest zdefiniowane.
W poniższych przypadkach zobaczylibyśmy, jak manipulować wartością this
.
Wywołanie funkcji na obiekcie
Można to zrobić na różne sposoby. Jeśli wywołałeś metody natywne w Javascript, jak forEach
i slice
, powinieneś już wiedzieć, że this
zmienna w tym przypadku odnosi się do funkcji, Object
na której wywołałeś tę funkcję (zwróć uwagę, że w javascript prawie wszystko jest an Object
, łącznie z Array
s i Function
s). Weźmy na przykład poniższy kod.
var myObj = {key: "Obj"};
myObj.logThis = function () {
// I am a method
console.log(this);
}
myObj.logThis(); // myObj is logged
Jeśli a Object
zawiera właściwość, która przechowuje a Function
, właściwość ta nazywana jest metodą. Ta metoda, po wywołaniu, zawsze będzie miała this
zmienną ustawioną na wartość, z Object
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, odniesienie do this
nie jest już zachowywane w nowej zmiennej. Na przykład:
// continuing with the previous code snippet
var myVar = myObj.logThis;
myVar();
// logs either of window/global/undefined based on mode of operation
Rozważając bardziej powszechnie praktyczny scenariusz:
var el = document.getElementById('idOfEl');
el.addEventListener('click', function() { console.log(this) });
// the function called by addEventListener contains this as the reference to the element
// so clicking on our element would log that element itself
Słowo new
kluczowe
Rozważmy funkcję konstruktora w JavaScript:
function Person (name) {
this.name = name;
this.sayHello = function () {
console.log ("Hello", this);
}
}
var awal = new Person("Awal");
awal.sayHello();
// In `awal.sayHello`, `this` contains the reference to the variable `awal`
Jak to działa? Cóż, zobaczmy, co się stanie, gdy użyjemy new
słowa kluczowego.
- Wywołanie funkcji ze
new
słowem kluczowym natychmiast zainicjowałobyObject
typ typePerson
. - Konstruktor this
Object
ma swój konstruktor ustawiony naPerson
. Zwróć też uwagę,typeof awal
że powróciObject
tylko. - Ten nowy
Object
miałby przypisany prototypPerson.prototype
. Oznacza to, że każda metoda lub właściwość wPerson
prototypie byłaby dostępna dla wszystkich wystąpieńPerson
, w tymawal
. - Sama funkcja
Person
jest teraz wywoływana;this
będący odniesieniem do nowo powstałego obiektuawal
.
Całkiem proste, co?
Zauważ, że oficjalna specyfikacja ECMAScript nigdzie nie stwierdza, że tego typu funkcje są rzeczywistymi constructor
funkcjami. Są to zwykłe funkcje i new
można ich używać w dowolnej funkcji. Po prostu używamy ich jako takich, więc nazywamy je tylko takimi.
Wywoływanie funkcji w funkcjach: call
iapply
Więc tak, ponieważ function
s są również Objects
(a właściwie zmiennymi pierwszej klasy w JavaScript), nawet funkcje mają metody, które są ... cóż, same funkcjami.
Wszystkie funkcje dziedziczą po zmiennej global Function
, a dwie z jej wielu metod to call
i apply
, a obie mogą być używane do manipulowania wartością this
funkcji, na której są wywoływane.
function foo () { console.log (this, arguments); }
var thisArg = {myObj: "is cool"};
foo.call(thisArg, 1, 2, 3);
To jest typowy przykład użycia call
. Zasadniczo przyjmuje pierwszy parametr i ustawia this
funkcję foo
jako odniesienie do thisArg
. Wszystkie inne parametry przekazywane do funkcji call
są przekazywane do funkcji foo
jako argumenty.
Tak więc powyższy kod zaloguje się {myObj: "is cool"}, [1, 2, 3]
do konsoli. Całkiem fajny sposób na zmianę wartości this
w dowolnej funkcji.
apply
jest prawie tym samym, co call
akceptuj, że przyjmuje tylko dwa parametry: thisArg
i tablicę zawierającą argumenty, które mają być przekazane do funkcji. Więc powyższe call
wezwanie można przetłumaczyć apply
tak:
foo.apply(thisArg, [1,2,3])
Zauważ, że call
i apply
może przesłonić wartość this
wywołania metody set by dot, które omówiliśmy w drugim punkcie. Wystarczająco proste :)
Przedstawiając .... bind
!
bind
jest bratem call
i apply
. Jest to również metoda dziedziczona przez wszystkie funkcje z Function
konstruktora globalnego w JavaScript. Różnica między bind
i call
/ apply
polega na tym, że oba call
i apply
faktycznie wywołają funkcję. bind
z drugiej strony zwraca nową funkcję z ustawieniem thisArg
i arguments
. Weźmy przykład, aby lepiej to zrozumieć:
function foo (a, b) {
console.log (this, arguments);
}
var thisArg = {myObj: "even more cool now"};
var bound = foo.bind(thisArg, 1, 2);
console.log (typeof bound); // logs `function`
console.log (bound);
/* logs `function () { native code }` */
bound(); // calling the function returned by `.bind`
// logs `{myObj: "even more cool now"}, [1, 2]`
Widzisz różnicę między tymi trzema? Jest subtelny, ale używa się ich inaczej. Podobnie jak call
i apply
, bind
również przesłaniają wartość this
ustawioną przez wywołanie metody kropkowej.
Należy również zauważyć, że żadna z tych trzech funkcji nie zmienia oryginalnej funkcji. call
i apply
zwróci wartość ze świeżo skonstruowanych funkcji, podczas gdy bind
zwróci świeżo skonstruowaną funkcję, gotową do wywołania.
Dodatkowe rzeczy, skopiuj to
Czasami nie podoba ci się fakt, że this
zmienia się wraz z zakresem, zwłaszcza zakresem zagnieżdżonym. Spójrz na poniższy przykład.
var myObj = {
hello: function () {
return "world"
},
myMethod: function () {
// copy this, variable names are case-sensitive
var that = this;
// callbacks ftw \o/
foo.bar("args", function () {
// I want to call `hello` here
this.hello(); // error
// but `this` references to `foo` damn!
// oh wait we have a backup \o/
that.hello(); // "world"
});
}
};
W powyższym kodzie widzimy, że wartość this
zmieniła się wraz z zakresem zagnieżdżonym, ale chcieliśmy, aby wartość była this
z oryginalnego zakresu. Więc „skopiowane” this
do that
i użyty zamiast kopiować this
. Sprytne, co?
Indeks:
- Co jest przetrzymywane
this
domyślnie? - A co by było, gdybyśmy wywołali tę funkcję jako metodę z notacją Object-dot?
- A jeśli użyjemy
new
słowa kluczowego? - Jak manipulujemy
this
zcall
iapply
? - Korzystanie
bind
. - Kopiowanie w
this
celu rozwiązania problemów z zakresem zagnieżdżonym.
„to” dotyczy zakresu. Każda funkcja ma swój własny zakres, a ponieważ wszystko w JS jest obiektem, nawet funkcja może przechowywać w sobie pewne wartości, używając „this”. OOP 101 uczy, że „this” ma zastosowanie tylko do instancji obiektu. Dlatego za każdym razem, gdy funkcja jest wykonywana, nowe „wystąpienie” tej funkcji ma nowe znaczenie „to”.
Większość ludzi jest zdezorientowanych, gdy próbują użyć „this” wewnątrz funkcji anonimowego zamknięcia, takich jak:
(funkcja (wartość) { this.value = wartość; $ ('. some-elements'). each (function (elt) { elt.innerHTML = this.value; // O o!! prawdopodobnie niezdefiniowany }); }) (2);
Więc tutaj, wewnątrz każdego (), „to” nie zawiera „wartości”, której oczekujesz (od
this.value = wartość;ponad tym). Tak więc, aby rozwiązać ten (niezamierzony) problem, programista może:
(funkcja (wartość) { var self = this; // mała zmiana self.value = wartość; $ ('. some-elements'). each (function (elt) { elt.innerHTML = self.value; // uff !! == 2 }); }) (2);
Wypróbuj to; zaczniesz lubić ten wzorzec programowania
Odkąd pojawił się ten wątek, zebrałem kilka punktów dla nowych czytelników this
.
Jaka jest wartość this
determinacji?
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”.
var person = {
firstName: "Penelope",
lastName: "Barrymore",
fullName: function () {
// We use "this" just as in the sentence above:
console.log(this.firstName + " " + this.lastName);
// We could have also written:
console.log(person.firstName + " " + person.lastName);
}
}
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 w window
obiekcie. Dlatego this
w funkcji globalnej odnosi się do window
obiektu globalnego (i ma taką wartość) .
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żywa this
, 2) przypisujemy metodę, która używa this
do zmiennej, 3) funkcja, która używa, this
jest przekazywana jako funkcja zwrotna i 4) this
jest używana wewnątrz domknięcia - funkcja wewnętrzna. (2)
Co przyniesie przyszłość
Zdefiniowane w ECMA Script 6 , funkcje strzałkowe przejmują this
powiązanie z otaczającego (funkcji lub globalnego) zakresu.
function foo() {
// return an arrow function
return (a) => {
// `this` here is lexically inherited from `foo()`
console.log(this.a);
};
}
var obj1 = { a: 2 };
var obj2 = { a: 3 };
var bar = foo.call(obj1);
bar.call( obj2 ); // 2, not 3!
Chociaż funkcje strzałkowe stanowią alternatywę dla używania bind()
, należy zauważyć, że zasadniczo wyłączają one tradycyjny this
mechanizm na rzecz szerzej rozumianego zakresu leksykalnego. (1)
Bibliografia:
- this & Object Prototypes , autorstwa Kyle'a Simpsona. © 2014 Getify Solutions.
- javascriptissexy.com - http://goo.gl/pvl0GX
- Angus Croll - http://goo.gl/Z2RacU
this
w JavaScript zawsze odnosi się do „właściciela” funkcji, który jest aktualnie wykonywany .
Jeśli nie zdefiniowano jawnego właściciela, następuje odwołanie do najwyższego właściciela, czyli obiektu okna.
Więc gdybym to zrobił
function someKindOfFunction() {
this.style = 'foo';
}
element.onclick = someKindOfFunction;
this
odwoływałby się do obiektu elementu. Ale uważaj, wiele osób popełnia ten błąd.
<element onclick="someKindOfFunction()">
W tym drugim przypadku wystarczy odwołać się do funkcji, a nie przekazać jej elementowi. Dlatego this
będzie odnosić się do obiektu okna.
Każdy kontekst wykonania w javascript ma ten parametr, który jest ustawiany przez:
- Jak wywoływana jest funkcja (w tym jako metoda obiektu, użycie wywołania i zastosowanie , użycie nowego )
- Korzystanie z wiązania
- Leksykalnie dla funkcji strzałkowych (przyjmują to z zewnętrznego kontekstu wykonania)
- Czy kod jest w trybie ścisłym czy nieścisłym
- Czy kod został wywołany przy użyciu eval
Możesz ustawić wartość tego za pomocą func.call
, func.apply
lub func.bind
.
Domyślnie, co dezorientuje większość początkujących, gdy detektor jest wywoływany po wywołaniu zdarzenia w elemencie DOM, wartością funkcji this jest element DOM.
jQuery sprawia, że zmiana w jQuery.proxy jest trywialna.
Daniel, niesamowite wyjaśnienie! Kilka słów na ten temat i dobra lista this
wskaźników kontekstu wykonania w przypadku obsługi zdarzeń.
W dwóch słowach, this
w JavaScript wskazuje obiekt, z którego (lub z którego kontekstu wykonania) została uruchomiona bieżąca funkcja i zawsze jest tylko do odczytu, i tak nie można jej ustawić (taka próba zakończy się błędem 'Invalid left-hand strona w przypisaniu ”.
W przypadku programów obsługi zdarzeń: wbudowane programy obsługi zdarzeń, takie jak <element onclick="foo">
, przesłaniają wszystkie inne programy obsługi dołączone wcześniej i wcześniej, dlatego należy zachować ostrożność i lepiej jest w ogóle unikać delegowania zdarzeń w tekście. I dzięki Zarze Alaverdyan, która zainspirowała mnie do tej listy przykładów poprzez odrębną debatę :)
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)">
Oto jedno dobre źródło this
w JavaScript
.
Oto podsumowanie:
to globalne
W przeglądarce w zakresie globalnym
this
jest towindow
obiekt<script type="text/javascript"> console.log(this === window); // true var foo = "bar"; console.log(this.foo); // "bar" console.log(window.foo); // "bar"
W przypadku
node
korzystania z repl,this
jest to najwyższa przestrzeń nazw. Możesz odnieść się do tego jakoglobal
.>this { ArrayBuffer: [Function: ArrayBuffer], Int8Array: { [Function: Int8Array] BYTES_PER_ELEMENT: 1 }, Uint8Array: { [Function: Uint8Array] BYTES_PER_ELEMENT: 1 }, ... >global === this true
Podczas
node
wykonywania ze skryptu,this
w zakresie globalnym zaczyna się jako pusty obiekt. To nie to samo, coglobal
\\test.js console.log(this); \\ {} console.log(this === global); \\ fasle
funkcjonować w ten sposób
Z wyjątkiem przypadków obsługi zdarzeń DOM lub gdy thisArg
podano a (patrz poniżej), zarówno w węźle, jak iw przeglądarce używającej this
funkcji, która nie jest wywoływana z new
odwołaniami do zakresu globalnego…
<script type="text/javascript">
foo = "bar";
function testThis() {
this.foo = "foo";
}
console.log(this.foo); //logs "bar"
testThis();
console.log(this.foo); //logs "foo"
</script>
Jeśli używasz use strict;
, w takim przypadku this
będzieundefined
<script type="text/javascript">
foo = "bar";
function testThis() {
"use strict";
this.foo = "foo";
}
console.log(this.foo); //logs "bar"
testThis(); //Uncaught TypeError: Cannot set property 'foo' of undefined
</script>
Jeśli wywołania funkcji z new
tym this
będzie nowym kontekście, nie będzie odwoływać się globalny this
.
<script type="text/javascript">
foo = "bar";
function testThis() {
this.foo = "foo";
}
console.log(this.foo); //logs "bar"
new testThis();
console.log(this.foo); //logs "bar"
console.log(new testThis().foo); //logs "foo"
</script>
- prototyp this
Utworzone funkcje stają się obiektami funkcji. Automatycznie uzyskują specjalną prototype
właściwość, do której można przypisać wartości. Kiedy tworzysz instancję, wywołując swoją funkcję new
, uzyskujesz dostęp do wartości przypisanych do prototype
właściwości. Dostęp do tych wartości uzyskuje się za pomocą this
.
function Thing() {
console.log(this.foo);
}
Thing.prototype.foo = "bar";
var thing = new Thing(); //logs "bar"
console.log(thing.foo); //logs "bar"
Zwykle błędem jest przypisywanie tablic lub obiektów w pliku prototype
. Jeśli chcesz, aby każda instancja miała własne tablice, utwórz je w funkcji, a nie w prototypie.
function Thing() {
this.things = [];
}
var thing1 = new Thing();
var thing2 = new Thing();
thing1.things.push("foo");
console.log(thing1.things); //logs ["foo"]
console.log(thing2.things); //logs []
- sprzeciwić się temu
Możesz użyć this
w dowolnej funkcji obiektu, aby odwołać się do innych właściwości tego obiektu. To nie to samo, co instancja utworzona za pomocą new
.
var obj = {
foo: "bar",
logFoo: function () {
console.log(this.foo);
}
};
obj.logFoo(); //logs "bar"
- DOM zdarzenie this
W module obsługi zdarzeń HTML DOM this
jest to zawsze odniesienie do elementu DOM, do którego zostało dołączone zdarzenie
function Listener() {
document.getElementById("foo").addEventListener("click",
this.handleClick);
}
Listener.prototype.handleClick = function (event) {
console.log(this); //logs "<div id="foo"></div>"
}
var listener = new Listener();
document.getElementById("foo").click();
Chyba że masz bind
kontekst
function Listener() {
document.getElementById("foo").addEventListener("click",
this.handleClick.bind(this));
}
Listener.prototype.handleClick = function (event) {
console.log(this); //logs Listener {handleClick: function}
}
var listener = new Listener();
document.getElementById("foo").click();
- HTML this
Wewnątrz atrybutów HTML, w których można umieścić JavaScript, this
znajduje się odniesienie do elementu.
<div id="foo" onclick="console.log(this);"></div>
<script type="text/javascript">
document.getElementById("foo").click(); //logs <div id="foo"...
</script>
- oceń to
Możesz użyć, eval
aby uzyskać dostęp this
.
function Thing () {
}
Thing.prototype.foo = "bar";
Thing.prototype.logFoo = function () {
eval("console.log(this.foo)"); //logs "bar"
}
var thing = new Thing();
thing.logFoo();
- z tym
Możesz użyć, with
aby dodać this
do bieżącego zakresu, aby odczytywać i zapisywać w wartościach this
bez this
jawnego odwoływania się do .
function Thing () {
}
Thing.prototype.foo = "bar";
Thing.prototype.logFoo = function () {
with (this) {
console.log(foo);
foo = "foo";
}
}
var thing = new Thing();
thing.logFoo(); // logs "bar"
console.log(thing.foo); // logs "foo"
- j Zapytaj o to
jQuery będzie w wielu miejscach this
odwoływać się do elementu DOM.
<div class="foo bar1"></div>
<div class="foo bar2"></div>
<script type="text/javascript">
$(".foo").each(function () { console.log(this); //logs <div class="foo... }); $(".foo").on("click", function () {
console.log(this); //logs <div class="foo...
});
$(".foo").each(function () {
this.click();
});
</script>
Istnieje wiele nieporozumień dotyczących interpretacji słowa kluczowego „this” w JavaScript. Miejmy nadzieję, że ten artykuł raz na zawsze pozwoli wszystkim 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, „this” zawsze odwołuje się do „bieżącego obiektu” w JavaScript. Jednak to, czym jest „bieżący obiekt”, różni się w zależności od kontekstu . Kontekst może być dokładnie 1 z 6 poniższych sytuacji:
- Globalny (tj. Poza wszystkimi funkcjami)
- Wewnętrzne bezpośrednie wywołanie „funkcji niezwiązanej” (tj. Funkcja, która nie została powiązana przez wywołanie functionName.bind )
- Wewnątrz pośrednia „funkcja niezwiązana” Wywołaj przez functionName.call i functionName.apply
- Wewnątrz wywołania „Bound Function” (tj. Funkcji, która została powiązana przez wywołanie functionName.bind )
- Podczas tworzenia obiektów przez „nowy”
- Wewnątrz modułu obsługi zdarzeń DOM Inline
Poniżej opisano kolejno każdy z tych kontekstów:
Kontekst globalny (tj. Poza wszystkimi funkcjami):
Poza wszystkimi funkcjami (tj. W kontekście globalnym) „bieżący obiekt” (a zatem wartość „this” ) jest zawsze obiektem „window” dla przeglądarek.
Wywołanie „Funkcja niezwiązana” Inside Direct :
Wewnątrz bezpośredniego wywołania „funkcji niezwiązanej” obiekt, który wywołał wywołanie funkcji, staje się „bieżącym obiektem” (i stąd wartością „this” ). Jeśli funkcja jest wywoływana bez jawnego bieżącego obiektu , bieżący obiekt jest albo obiektem "okna" (dla trybu nieścisłego), albo niezdefiniowanym (dla trybu ścisłego). Każda funkcja (lub zmienna) zdefiniowana w Global Context automatycznie staje się właściwością obiektu "window". Na przykład funkcja Suppose jest zdefiniowana w Global Context jako
function UserDefinedFunction(){ alert(this) }
staje się własnością obiektu window, tak jakbyś zdefiniował go jako
window.UserDefinedFunction=function(){ alert(this) }
W trybie "Non Strict", wywołanie / wywołanie tej funkcji bezpośrednio przez "UserDefinedFunction ()" automatycznie wywoła / wywoła ją jako "window.UserDefinedFunction ()" czyniąc "okno" jako "bieżący obiekt" (i stąd wartość " this " ) w " UserDefinedFunction ". Wywołanie tej funkcji w" Trybie nieostrym "spowoduje następujące
UserDefinedFunction() // displays [object Window] as it automatically gets invoked as window.UserDefinedFunction()
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 polu „UserDefinedFunction” będzie niezdefiniowane . Wywołanie tej funkcji w „Trybie ścisłym” spowoduje następujące skutki
UserDefinedFunction() // displays undefined
Jednak wywołanie go jawnie przy użyciu obiektu okna powinno skutkować następującym
window.UserDefinedFunction() // "always displays [object Window] irrespective of mode."
Spójrzmy na inny przykład. Proszę spojrzeć na poniższy kod
function UserDefinedFunction() { alert(this.a + "," + this.b + "," + this.c + "," + this.d) } var o1={ a:1, b:2, f:UserDefinedFunction } var o2={ c:3, d:4, f:UserDefinedFunction } o1.f() // Shall display 1,2,undefined,undefined o2.f() // Shall display undefined,undefined,3,4
W powyższym przykładzie widzimy, że kiedy "UserDefinedFunction" została wywołana przez o1 , "this" przyjmuje wartość o1 i zostaje wyświetlona wartość jego 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średniego wywołania „funkcji niezwiązanej” przez functionName.call i functionName.apply :
Gdy funkcja „Non Bound Function” jest wywoływana przez functionName.call lub functionName.apply , „bieżący obiekt” (i stąd wartość „this” ) jest ustawiana na wartość „this” parametru (pierwszego parametru) przekazanego do wywołania / aplikuj . Poniższy kod demonstruje to samo.
function UserDefinedFunction() { alert(this.a + "," + this.b + "," + this.c + "," + this.d) } var o1={ a:1, b:2, f:UserDefinedFunction } var o2={ c:3, d:4, f:UserDefinedFunction } UserDefinedFunction.call(o1) // Shall display 1,2,undefined,undefined UserDefinedFunction.apply(o1) // Shall display 1,2,undefined,undefined UserDefinedFunction.call(o2) // Shall display undefined,undefined,3,4 UserDefinedFunction.apply(o2) // Shall display undefined,undefined,3,4 o1.f.call(o2) // Shall display undefined,undefined,3,4 o1.f.apply(o2) // Shall display undefined,undefined,3,4 o2.f.call(o1) // Shall display 1,2,undefined,undefined o2.f.apply(o1) // Shall display 1,2,undefined,undefined
Powyższy kod wyraźnie pokazuje, że wartość „this” dla dowolnej funkcji „NON Bound” może zostać zmieniona przez wywołanie / zastosowanie . Ponadto, jeśli parametr „this” nie jest jawnie przekazywany do wywołania / zastosowania , „obiekt bieżący” (a zatem wartość „this”) jest ustawiany na „okno” w trybie nieścisłym i „niezdefiniowany” w trybie ścisłym.
Wewnątrz wywołania „Bound Function” (tj. Funkcji, która została powiązana przez wywołanie functionName.bind ):
Funkcja powiązana to funkcja, której „ta” wartość została ustalona. Poniższy kod pokazuje, jak „this” działa w przypadku powiązanej funkcji
function UserDefinedFunction() { alert(this.a + "," + this.b + "," + this.c + "," + this.d) } var o1={ a:1, b:2, f:UserDefinedFunction, bf:null } var o2={ c:3, d:4, f:UserDefinedFunction, bf:null } var bound1=UserDefinedFunction.bind(o1); // permanantly fixes "this" value of function "bound1" to Object o1 bound1() // Shall display 1,2,undefined,undefined var bound2=UserDefinedFunction.bind(o2); // permanantly fixes "this" value of function "bound2" to Object o2 bound2() // Shall display undefined,undefined,3,4 var bound3=o1.f.bind(o2); // permanantly fixes "this" value of function "bound3" to Object o2 bound3() // Shall display undefined,undefined,3,4 var bound4=o2.f.bind(o1); // permanantly fixes "this" value of function "bound4" to Object o1 bound4() // Shall display 1,2,undefined,undefined o1.bf=UserDefinedFunction.bind(o2) // permanantly fixes "this" value of function "o1.bf" to Object o2 o1.bf() // Shall display undefined,undefined,3,4 o2.bf=UserDefinedFunction.bind(o1) // permanantly fixes "this" value of function "o2.bf" to Object o1 o2.bf() // Shall display 1,2,undefined,undefined bound1.call(o2) // Shall still display 1,2,undefined,undefined. "call" cannot alter the value of "this" for bound function bound1.apply(o2) // Shall still display 1,2,undefined,undefined. "apply" cannot alter the value of "this" for bound function o2.bf.call(o2) // Shall still display 1,2,undefined,undefined. "call" cannot alter the value of "this" for bound function o2.bf.apply(o2) // Shall still display 1,2,undefined,undefined."apply" cannot alter the value of "this" for bound function
Jak podano w powyższym kodzie, „ta” wartość dla żadnej „funkcji powiązanej” NIE MOŻE zostać zmieniona przez wywołanie / zastosowanie . Ponadto, jeśli parametr „this” nie jest jawnie przekazywany do wiązania, „bieżący obiekt” (i stąd wartość „this” ) jest ustawiany na „okno” w trybie nieścisłym i „niezdefiniowany” w trybie ścisłym. Jeszcze jedna rzecz. Powiązanie już powiązanej funkcji nie zmienia wartości „this” . Pozostaje ustawiona jako wartość ustawiona przez pierwszą funkcję wiązania.
Podczas tworzenia obiektów przez „nowy” :
Wewnątrz funkcji konstruktora „bieżący obiekt” (a zatem wartość „this” ) odwołuje się do aktualnie tworzonego obiektu poprzez „nowy”, niezależnie od statusu powiązania funkcji. Jeśli jednak konstruktor jest funkcją powiązaną, powinien zostać wywołany z predefiniowanym zestawem argumentów, takim jak dla funkcji powiązanej.
Wewnętrzna procedura obsługi zdarzeń DOM :
Proszę spojrzeć na następujący fragment kodu HTML
<button onclick='this.style.color=white'>Hello World</button> <div style='width:100px;height:100px;' onclick='OnDivClick(event,this)'>Hello World</div>
„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 kliknięcie elementu „div” powoduje wywołanie funkcji OnDivClick z drugim parametrem odwołującym się do klikniętego elementu div. Jednak wartość „this” w OnDivClick NIE MUSI odwoływać 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, jest ona wywoływana w kontekście obiektu ( „obiekt bieżący” ). Jeśli bieżący obiekt nie jest jawnie podany, bieżący obiekt jest „obiektem okna” w trybie innym niż ścisły i „nieokreślony” w trybie ścisłym.
Wartość „this” w funkcji niezwiązanej jest odniesieniem do obiektu, w kontekście którego funkcja jest wywoływana ( „bieżący obiekt” )
Wartość „this” w funkcji niezwiązanej może zostać zastąpiona przez wywołanie i zastosowanie metod funkcji.
Wartość „this” jest ustalona dla funkcji Bound i nie może być zastąpiona przez wywołanie i zastosowanie metod funkcji.
Wiązanie i już powiązana funkcja nie zmienia wartości „this”. Pozostaje ustawiona jako wartość ustawiona przez pierwszą funkcję wiązania.
Wartość „this” w konstruktorze to obiekt, który jest tworzony i inicjowany
Wartość „this” w wbudowanej procedurze obsługi zdarzeń DOM jest odniesieniem do elementu, dla którego podano procedurę obsługi zdarzeń.
Prawdopodobnie najbardziej szczegółowy i wyczerpujący artykuł na temat this
jest następujący:
Delikatne wyjaśnienie słowa kluczowego „this” w JavaScript
Pomysł this
polega na zrozumieniu, że typy wywołań funkcji mają istotne znaczenie przy ustawianiu this
wartości.
Mając kłopoty z identyfikacją this
, nie zadawaj sobie pytań:
Skąd
this
pochodzi ?
ale nie należy zadać sobie pytanie:
Jak wywoływana jest funkcja ?
W przypadku funkcji strzałki (szczególny przypadek przezroczystości kontekstu) zadaj sobie pytanie:
Jaka wartość ma miejsce, w
this
którym zdefiniowano funkcję strzałki ?
Ten sposób myślenia jest właściwy, gdy this
masz do czynienia z bólem głowy i uchroni Cię przed bólem głowy.
Jest to najlepsze wyjaśnienie widziałem: Zrozumieć JavaScripts to z jasnością
To odniesienie zawsze odnosi się do (i posiada wartość) obiektowy osobliwy obiektowego i jest zwykle używany wewnątrz funkcji lub metody, ale można go stosować poza funkcją w zasięgu globalnym. Zauważ, że kiedy używamy trybu ścisłego, zachowuje on wartość undefined w funkcjach globalnych i funkcjach anonimowych, które nie są powiązane z żadnym obiektem.
Istnieją cztery scenariusze, w których może to być mylące:
- Kiedy przekazujemy metodę (która używa this ) jako argument, który ma być użyty jako funkcja zwrotna.
- Kiedy używamy funkcji wewnętrznej (domknięcia). Należy zauważyć, że zamknięcia nie mogą uzyskać dostępu do zmiennej this funkcji zewnętrznej przy użyciu słowa kluczowego this, ponieważ zmienna this jest dostępna tylko dla samej funkcji, a nie dla funkcji wewnętrznych.
- Kiedy to metoda, która polega na tym jest przypisany do zmiennej całej kontekstach, w tym przypadku to referencje inny obiekt niż pierwotnie przeznaczone.
- Używając tego razem z metodami bind, apply i call.
Podaje przykłady kodu, wyjaśnienia i rozwiązania, które moim zdaniem były bardzo pomocne.
this
jest jedną z niezrozumiałych koncepcji w JavaScript, ponieważ zachowuje się trochę inaczej w zależności od miejsca. Po prostu this
odnosi się do „właściciela” funkcji, którą aktualnie wykonujemy .
this
pomaga uzyskać bieżący obiekt (inaczej kontekst wykonania), z którym pracujemy. Jeśli rozumiesz, w którym obiekcie wykonywana jest bieżąca funkcja, możesz łatwo zrozumieć, co this
jest bieżące
var val = "window.val"
var obj = {
val: "obj.val",
innerMethod: function () {
var val = "obj.val.inner",
func = function () {
var self = this;
return self.val;
};
return func;
},
outerMethod: function(){
return this.val;
}
};
//This actually gets executed inside window object
console.log(obj.innerMethod()()); //returns window.val
//Breakdown in to 2 lines explains this in detail
var _inn = obj.innerMethod();
console.log(_inn()); //returns window.val
console.log(obj.outerMethod()); //returns obj.val
Powyżej tworzymy 3 zmienne o tej samej nazwie „val”. Jeden w kontekście globalnym, jeden wewnątrz obiektu, a drugi wewnątrz innerMethod of obj. JavaScript rozpoznaje identyfikatory w określonym kontekście, przechodząc w górę łańcucha zasięgu od lokalnego do globalnego.
Niewiele miejsc, w których this
można je rozróżnić
Wywołanie metody obiektu
var status = 1;
var helper = {
status : 2,
getStatus: function () {
return this.status;
}
};
var theStatus1 = helper.getStatus(); //line1
console.log(theStatus1); //2
var theStatus2 = helper.getStatus;
console.log(theStatus2()); //1
Kiedy wykonywana jest linia 1, JavaScript ustanawia kontekst wykonania (EC) dla wywołania funkcji, ustawiając this
na obiekt , do którego odwołuje się cokolwiek, co pojawiło się przed ostatnim „”. . więc w ostatnim wierszu można zrozumieć, że a()
zostało wykonane w kontekście globalnym, którym jest window
.
Z Constructor
this
może służyć do odwoływania się do tworzonego obiektu
function Person(name){
this.personName = name;
this.sayHello = function(){
return "Hello " + this.personName;
}
}
var person1 = new Person('Scott');
console.log(person1.sayHello()); //Hello Scott
var person2 = new Person('Hugh');
var sayHelloP2 = person2.sayHello;
console.log(sayHelloP2()); //Hello undefined
Kiedy Person()
wykonywany jest nowy, tworzony jest zupełnie nowy obiekt. Person
jest wywoływana i this
jest ustawiona na odniesienie do tego nowego obiektu.
Wywołanie funkcji
function testFunc() {
this.name = "Name";
this.myCustomAttribute = "Custom Attribute";
return this;
}
var whatIsThis = testFunc();
console.log(whatIsThis); //window
var whatIsThis2 = new testFunc();
console.log(whatIsThis2); //testFunc() / object
console.log(window.myCustomAttribute); //Custom Attribute
Jeśli pominiemy new
słowo kluczowe, whatIsThis
odsyła do najbardziej globalnego kontekstu, jaki może znaleźć ( window
)
Z obsługą zdarzeń
Jeśli program obsługi zdarzeń jest wbudowany, this
odwołuje się do obiektu globalnego
<script type="application/javascript">
function click_handler() {
alert(this); // alerts the window object
}
</script>
<button id='thebutton' onclick='click_handler()'>Click me!</button>
Podczas dodawania this
modułu obsługi zdarzeń za pomocą JavaScript odwołuje się do elementu DOM, który wygenerował zdarzenie.
- Możesz także manipulować kontekstem za pomocą
.apply()
.call()
i.bind()
- JQuery proxy to kolejny sposób, dzięki któremu możesz upewnić się, że ta funkcja będzie miała pożądaną wartość. (Sprawdź zrozumienie użycia $ .proxy () , jQuery.proxy () )
- Co var that = thisoznacza w JavaScript
Mówiąc pseudoklasycznie, sposób, w jaki na wielu wykładach uczy się słowa kluczowego „this”, polega na tym, że jest to obiekt, którego instancję tworzy klasa lub konstruktor obiektu. Za każdym razem, gdy nowy obiekt jest konstruowany z klasy, wyobraź sobie, że pod maską jest tworzona i zwracana lokalna instancja obiektu „this”. Pamiętam, jak tego nauczono:
function Car(make, model, year) {
var this = {}; // under the hood, so to speak
this.make = make;
this.model = model;
this.year = year;
return this; // under the hood
}
var mycar = new Car('Eagle', 'Talon TSi', 1993);
// ========= under the hood
var this = {};
this.make = 'Eagle';
this.model = 'Talon TSi';
this.year = 1993;
return this;
Wartość „this” zależy od „kontekstu”, w którym funkcja jest wykonywana. Kontekstem może być dowolny obiekt lub obiekt globalny, np. Okno.
Zatem semantyka „tego” różni się od tradycyjnych języków OOP. I powoduje problemy: 1. gdy funkcja jest przekazywana do innej zmiennej (najprawdopodobniej wywołanie zwrotne); i 2. gdy domknięcie jest wywoływane z metody składowej klasy.
W obu przypadkach jest to ustawione na window.
Czy to pomoże? (Największe zamieszanie związane z 'this' w javascript wynika z faktu, że generalnie nie jest ono połączone z twoim obiektem, ale z aktualnym zakresem wykonywania - to może nie być dokładnie tak, jak to działa, ale zawsze tak mi się wydaje - zobacz artykuł, aby uzyskać pełne wyjaśnienie)
Trochę informacji o tym słowie kluczowym
Zalogujmy this
słowo kluczowe do konsoli w zakresie globalnym bez żadnego dodatkowego kodu, ale
console.log(this)
W kliencie / przeglądarce this
słowo kluczowe jest globalnym obiektem, którym jestwindow
console.log(this === window) // true
i
W środowisku wykonawczym Server / Node / Javascript this
słowo kluczowe jest również obiektem globalnym, którym jestmodule.exports
console.log(this === module.exports) // true
console.log(this === exports) // true
Pamiętaj, że exports
to tylko odniesienie domodule.exports
to użycie dla Scope, tak jak to
<script type="text/javascript" language="javascript">
$('#tbleName tbody tr').each(function{ var txt=''; txt += $(this).find("td").eq(0).text();
\\same as above but synatx different
var txt1='';
txt1+=$('#tbleName tbody tr').eq(0).text();
alert(txt1)
});
</script>
wartość txt1 i txt jest taka sama w powyższym przykładzie $ (this) = $ ('# tbleName tbody tr') jest taka sama
Mam inne podejście this
do odpowiedzi i mam nadzieję, że jest to pomocne.
Jednym ze sposobów spojrzenia na JavaScript jest stwierdzenie, że istnieje tylko jeden sposób wywołania funkcji 1 . To jest
functionObject.call(objectForThis, arg0, arg1, arg2, ...);
Zawsze jest podana jakaś wartość objectForThis
.
Wszystko inne to cukier syntaktyczny functionObject.call
A więc wszystko inne można opisać przez to, jak to się przekłada functionObject.call
.
Jeśli wywołujesz po prostu funkcję, this
jest to „obiekt globalny”, którym w przeglądarce jest okno
function foo() {
console.log(this);
}
foo(); // this is the window object
Innymi słowy,
foo();
został skutecznie przetłumaczony na
foo.call(window);
Zauważ, że jeśli używasz trybu ścisłego, this
będzieundefined
'use strict';
function foo() {
console.log(this);
}
foo(); // this is the window object
co znaczy
Innymi słowy,
foo();
został skutecznie przetłumaczony na
foo.call(undefined);
W JavaScript istnieją operatory takie jak +
i -
i *
. Jest też operator kropki.
.
Operatora w przypadku korzystania z funkcji po prawej i po lewej obiektu skutecznie oznacza „przejścia przedmiot this
funkcjonować.
Przykład
const bar = {
name: 'bar',
foo() {
console.log(this);
},
};
bar.foo(); // this is bar
Innymi słowy, bar.foo()
przekłada się naconst temp = bar.foo; temp.call(bar);
Zauważ, że nie ma znaczenia, w jaki sposób funkcja została utworzona (głównie ...). Wszystko to przyniesie takie same wyniki
const bar = {
name: 'bar',
fn1() { console.log(this); },
fn2: function() { console.log(this); },
fn3: otherFunction,
};
function otherFunction() { console.log(this) };
bar.fn1(); // this is bar
bar.fn2(); // this is bar
bar.fn3(); // this is bar
Znowu to wszystko jest tylko cukrem syntaktycznym
{ const temp = bar.fn1; temp.call(bar); }
{ const temp = bar.fn2; temp.call(bar); }
{ const temp = bar.fn3; temp.call(bar); }
Kolejną zmarszczką jest łańcuch prototypów. Kiedy używasz a.b
JavaScript najpierw sprawdza obiekt, do którego odwołuje się bezpośrednio a
właściwość b
. Jeśli b
nie zostanie znaleziony w obiekcie, JavaScript będzie szukał w prototypie obiektu, aby znaleźć b
.
Istnieją różne sposoby definiowania prototypu obiektu, najczęściej w 2019 roku jest class
słowo kluczowe. Na potrzeby tego this
jednak nie ma to znaczenia. Liczy się to, że gdy szuka w obiekcie a
właściwości, b
jeśli znajdzie właściwość b
na obiekcie lub w jego łańcuchu prototypów, jeśli b
kończy się to funkcją, obowiązują te same zasady, co powyżej. b
Odwołania do funkcji zostaną wywołane przy użyciu call
metody i przekazane a
jako objectForThis, jak pokazano na początku tej odpowiedzi.
Teraz. Wyobraźmy sobie, że tworzymy funkcję, która jawnie ustawia this
przed wywołaniem innej funkcji, a następnie wywołujemy ją za pomocą .
operatora (kropki)
function foo() {
console.log(this);
}
function bar() {
const objectForThis = {name: 'moo'}
foo.call(objectForThis); // explicitly passing objectForThis
}
const obj = {
bar,
};
obj.bar();
Po przetłumaczeniu do użycia call
, obj.bar()
staje się const temp = obj.bar; temp.call(obj);
. Kiedy wchodzimy do bar
funkcji, którą wywołujemy, foo
ale jawnie przekazaliśmy inny obiekt dla objectForThis, więc kiedy dochodzimy do foo, this
jest ten obiekt wewnętrzny.
To jest to, co skutecznie robią obie bind
i =>
funkcje. Są bardziej syntaktycznym cukrem. Skutecznie budują nową niewidoczną funkcję, dokładnie tak jak bar
powyżej, która jawnie ustawia, this
zanim wywoła jakąkolwiek określoną funkcję. W przypadku bind this
jest ustawiany na wszystko, do czego przejdziesz bind
.
function foo() {
console.log(this);
}
const bar = foo.bind({name: 'moo'});
// bind created a new invisible function that calls foo with the bound object.
bar();
// the objectForThis we are passing to bar here is ignored because
// the invisible function that bind created will call foo with with
// the object we bound above
bar.call({name: 'other'});
Zauważ, że gdyby functionObject.bind
nie istniało, moglibyśmy stworzyć własne w ten sposób
function bind(fn, objectForThis) {
return function(...args) {
return fn.call(objectForthis, ...args);
};
}
a potem moglibyśmy to tak nazwać
function foo() {
console.log(this);
}
const bar = bind(foo, {name:'abc'});
Funkcje strzałkowe, =>
operator to cukier syntaktyczny dla wiązania
const a = () => {console.log(this)};
jest taki sam jak
const tempFn = function() {console.log(this)};
const a = tempFn.bind(this);
Podobnie bind
, tworzona jest nowa niewidoczna funkcja, która wywołuje daną funkcję z powiązaną wartością for, objectForThis
ale w przeciwieństwie bind
do obiektu, który ma być powiązany, jest niejawna. To wszystko, co this
dzieje się, gdy =>
operator jest używany.
Tak więc, podobnie jak powyższe zasady
const a = () => { console.log(this); } // this is the global object
'use strict';
const a = () => { console.log(this); } // this is undefined
function foo() {
return () => { console.log(this); }
}
const obj = {
foo,
};
const b = obj.foo();
b();
obj.foo()
przekłada się na, const temp = obj.foo; temp.call(obj);
co oznacza, że operator strzałki wewnątrz foo
będzie wiązał obj
się z nową niewidzialną funkcją i zwróci tę nową niewidoczną funkcję, do której jest przypisana b
. b()
będzie działać tak, jak zawsze, b.call(window)
lub b.call(undefined)
wywołując nową niewidzialną funkcję, która została foo
utworzona. Ta niewidoczna funkcja ignoruje this
przekazane do niej dane i przekazuje obj
jako obiektForThis` do funkcji strzałkowej.
Powyższy kod tłumaczy się na
function foo() {
function tempFn() {
console.log(this);
}
return tempFn.bind(this);
}
const obj = {
foo,
};
const b = obj.foo();
b.call(window or undefined if strict mode);
1apply
to kolejna funkcja podobna docall
functionName.apply(objectForThis, arrayOfArgs);
Ale od ES6 koncepcyjnie możesz to nawet przetłumaczyć na
functionName.call(objectForThis, ...arrayOfArgs);
Podsumowanie this
JavaScript:
- Wartość
this
jest określana przez to, w jaki sposób funkcja jest wywoływana, a nie gdzie została utworzona! - Zwykle wartość
this
jest określana przez obiekt, który znajduje się na lewo od kropki. (window
w przestrzeni globalnej) - W detektorach zdarzeń wartość
this
odnosi się do elementu DOM, na którym zdarzenie zostało wywołane. - Gdy funkcja in function jest wywoływana ze
new
słowem kluczowym, wartośćthis
odnosi się do nowo utworzonego obiektu - Można manipulować wartość
this
z funkcjami:call
,apply
,bind
Przykład:
let object = {
prop1: function () {console.log(this);}
}
object.prop1(); // object is left of the dot, thus this is object
const myFunction = object.prop1 // We store the function in the variable myFunction
myFunction(); // Here we are in the global space
// myFunction is a property on the global object
// Therefore it logs the window object
Przykładowe detektory zdarzeń:
document.querySelector('.foo').addEventListener('click', function () {
console.log(this); // This refers to the DOM element the eventListener was invoked from
})
document.querySelector('.foo').addEventListener('click', () => {
console.log(this); // Tip, es6 arrow function don't have their own binding to the this v
}) // Therefore this will log the global object
.foo:hover {
color: red;
cursor: pointer;
}
<div class="foo">click me</div>
Przykładowy konstruktor:
function Person (name) {
this.name = name;
}
const me = new Person('Willem');
// When using the new keyword the this in the constructor function will refer to the newly created object
console.log(me.name);
// Therefore, the name property was placed on the object created with new keyword.
Aby właściwie zrozumieć „to”, należy zrozumieć kontekst i zakres oraz różnicę między nimi.
Zakres : W javascript zakres jest powiązany z widocznością zmiennych, zakres osiągany jest 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ę ono do obiektu, do którego należy funkcja. Na przykład wewnątrz funkcji, kiedy mówisz: „this.accoutNumber”, odnosisz się do właściwości „accoutNumber”, która należy do obiektu, do którego należy ta funkcja.
Jeśli obiekt „myObj” ma metodę o nazwie „getMyName”, gdy słowo kluczowe JavaScript „this” jest używane wewnątrz „getMyName”, odnosi się do „myObj”. Jeśli funkcja „getMyName” została wykonana w zasięgu globalnym, to „this” odnosi się do obiektu okna (z wyjątkiem trybu ścisłego).
Zobaczmy teraz przykład:
<script>
console.log('What is this: '+this);
console.log(this);
</script>
Uruchomiony abobve kod w danych wyjściowych przeglądarki:
Zgodnie z danymi wyjściowymi, w których znajdujesz się w kontekście obiektu okna, widoczne jest również, że prototyp okna odnosi się do obiektu.
Teraz spróbujmy wewnątrz funkcji:
<script>
function myFunc(){
console.log('What is this: '+this);
console.log(this);
}
myFunc();
</script>
Wynik:
Teraz stwórzmy nasz własny obiekt. W javascript możesz stworzyć obiekt na wiele sposobów.
<script>
var firstName = "Nora";
var lastName = "Zaman";
var myObj = {
firstName:"Lord",
lastName:'Baron',
printNameGetContext:function(){
console.log(firstName + " "+lastName);
console.log(this.firstName +" "+this.lastName);
return this;
}
}
var context = myObj.printNameGetContext();
console.log(context);
</script>
Wynik:
Z powyższego przykładu stwierdziliśmy, że słowo kluczowe „this” odnosi się do nowego kontekstu związanego z myObj, a myObject ma również łańcuch prototypów do Object.
Rzućmy kolejny przykład:
<body>
<button class="btn">Click Me</button>
<script>
function printMe(){
//Terminal2: this function declared inside window context so this function belongs to the window object.
console.log(this);
}
document.querySelector('.btn').addEventListener('click', function(){
//Terminal1: button context, this callback function belongs to DOM element
console.log(this);
printMe();
})
</script>
</body>
wyjście: ma sens, prawda? (przeczytaj komentarze)
Jeśli masz problem ze zrozumieniem powyższego przykładu, spróbujmy z naszym własnym oddzwonieniem;
<script>
var myObj = {
firstName:"Lord",
lastName:'Baron',
printName:function(callback1, callback2){
//Attaching callback1 with this myObj context
this.callback1 = callback1;
this.callback1(this.firstName +" "+this.lastName)
//We did not attached callback2 with myObj so, it's reamin with window context by default
callback2();
/*
//test bellow codes
this.callback2 = callback2;
this.callback2();
*/
}
}
var callback2 = function (){
console.log(this);
}
myObj.printName(function(data){
console.log(data);
console.log(this);
}, callback2);
</script>
wynik:
Zrozummy teraz zakres, jaźń, IIFE i TO, jak się zachowuje
var color = 'red'; // property of window
var obj = {
color:'blue', // property of window
printColor: function(){ // property of obj, attached with obj
var self = this;
console.log('In printColor -- this.color: '+this.color);
console.log('In printColor -- self.color: '+self.color);
(function(){ // decleard inside of printColor but not property of object, it will executed on window context.
console.log(this)
console.log('In IIFE -- this.color: '+this.color);
console.log('In IIFE -- self.color: '+self.color);
})();
function nestedFunc(){// decleard inside of printColor but not property of object, it will executed on window context.
console.log('nested fun -- this.color: '+this.color);
console.log('nested fun -- self.color: '+self.color);
}
nestedFunc(); // executed on window context
return nestedFunc;
}
};
obj.printColor()(); // returned function executed on window context
</script>
Wynik jest całkiem niezły, prawda?