Jak działa słowo kluczowe „to”?

Jun 27 2010

Zauważyłem, że wydaje się, że nie ma jasnego wyjaśnienia, czym thisjest 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 thisdziała i kiedy należy go używać?

Odpowiedzi

1378 DanielTrebbien Jun 27 2010 at 20:15

Polecam najpierw przeczytać artykuł Mike'a Westa Scope in JavaScript ( mirror ). Jest to doskonałe, przyjazne wprowadzenie do koncepcji thisi ł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.1this kluczowe

Do thisocenia 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 ( objw 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ść, thisArgktó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.prototypefunkcji są one wywoływane w obiekcie funkcji, ale zamiast ustawiać ThisBinding na obiekt funkcji, ThisBinding jest ustawiana na thisArg.

W przypadku Array.prototypefunkcji dana callbackfnjest wywoływana w kontekście wykonywania, w którym wartość ThisBinding jest ustawiona na, thisArgjeś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ę thisdo funkcji bibliotecznych należy zapoznać się z dokumentacją, aby uzyskać wszelkie gwarancje dotyczące tego, jaka jest wartość, thisgdy 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 newoperatora 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ą thisjest 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łkowej this... odwołuje się (s) do wartości thisś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.

  1. Jaka jest wartość thisw zaznaczonej linii? Dlaczego?

window - Zaznaczona linia jest oceniana w początkowym globalnym kontekście wykonania.

    if (true) {
        // What is `this` here?
    }
  1. Jaka jest wartość thisw zaznaczonej linii, kiedy obj.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);
  

  1. Jaka jest wartość thisw zaznaczonej linii? Dlaczego?

window

W tym przykładzie interpreter JavaScript wprowadza kod funkcji, ale ponieważ myFun/ obj.myMethodnie jest wywoływana w obiekcie, wartość ThisBinding jest ustawiona na window.

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);
  

  1. Jaka jest wartość thisw zaznaczonej linii? Dlaczego?

window

Ten był trudny. Podczas oceny kodu eval, thisjest obj. Jednak w kodzie eval myFunnie jest wywoływana na obiekcie, więc ThisBinding jest ustawiona na windowdla 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()");
        }
    };
  1. Jaka jest wartość thisw zaznaczonej linii? Dlaczego?

obj

Linia myFun.call(obj);wywołuje specjalną wbudowaną funkcję Function.prototype.call(), która przyjmuje thisArgjako 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);
  

168 Mahesha999 Jul 08 2013 at 00:32

Że thiszachowuje się różnie w JavaScript słów kluczowych w porównaniu do innych języków. W językach zorientowanych obiektowo thissłowo kluczowe odnosi się do bieżącej instancji klasy. W JavaScript wartość funkcji thisjest 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 thisw kontekście globalnym, jest on powiązany z obiektem globalnym ( windoww przeglądarce)

document.write(this);  //[object Window]

Kiedy używasz thiswewnątrz funkcji zdefiniowanej w kontekście globalnym, thisjest 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 f1jest wykonana metoda obiektu globalnego. Zatem możemy to również wywołać na windowobiekcie 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 thissłowa kluczowego wewnątrz metody obiektu, thisjest 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, thiszostanie 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 thisnadal 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 thisfunkcji wewnętrznej, która jest wywoływana bez kontekstu (tj. Nie na żadnym obiekcie), jest ona powiązana z obiektem globalnym ( windoww 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ą newoperatora.
  • 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 thiswersjami, 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 newsłowem kluczowym), thiswewną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, thiswewną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ć, thisjaka 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])Ustawia obj1jako wartość thisinside fun()i wywołuje fun()przekazywanie elementów argsArrayjako argumenty.
  • fun.call(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])- Ustawia obj1wartość thisinside fun()i wywołuje fun()przekazanie arg1, arg2, arg3, ...jako jej argumenty.
  • fun.bind(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])- Zwraca odniesienie do funkcji funz thiswewnętrzną zabawą powiązaną obj1i parametrami funpowiązania z określonymi parametrami arg1, arg2, arg3,....
  • Do tej pory różnica między apply, calli bindmusiało stać się widoczne. applypozwala określić argumenty, które mają funkcjonować jako obiekt tablicowy, tj. obiekt z lengthwłaściwością numeryczną i odpowiadającymi jej właściwościami nieujemnych liczb całkowitych. Natomiast callpozwala bezpośrednio określić argumenty funkcji. Zarówno applyi callnatychmiast wywołuje funkcję w określonym kontekście iz określonymi argumentami. Z drugiej strony bindpo prostu zwraca funkcję powiązaną z określoną thiswartoś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. thiswewnętrzne programy obsługi zdarzeń

  • Kiedy przypisujesz funkcję bezpośrednio do programów obsługi zdarzeń elementu, użycie thisbezpośrednio wewnątrz funkcji obsługi zdarzeń odnosi się do odpowiedniego elementu. Takie bezpośrednie przypisanie funkcji można wykonać addeventListenermetodą lub tradycyjnymi metodami rejestracji zdarzeń, takimi jak onclick.
  • Podobnie, gdy używasz thisbezpośrednio wewnątrz właściwości zdarzenia (np. <button onclick="...this..." >) Elementu, odwołuje się do elementu.
  • Jednak użycie thispośrednio przez inną funkcję wywoływaną wewnątrz funkcji obsługi zdarzenia lub właściwości zdarzenia jest rozpoznawane jako obiekt globalny window.
  • 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. thisw funkcji strzałek ES6

W funkcji strzałkowej thiszachowuje 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 
66 user3459110 Oct 26 2014 at 22:07

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ść thisbyłaby rejestrowana jako window. Dzieje się tak, ponieważ windowjest to zmienna globalna w zakresie przeglądarki internetowej.

Jeśli uruchomisz ten sam fragment kodu w środowisku takim jak node.js, thisodniesie 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, thisnie będzie już odnosić się do zmiennej globalnej w żadnym ze środowisk. Ma to na celu uniknięcie nieporozumień w trybie ścisłym. thisw 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 forEachi slice, powinieneś już wiedzieć, że thiszmienna w tym przypadku odnosi się do funkcji, Objectna której wywołałeś tę funkcję (zwróć uwagę, że w javascript prawie wszystko jest an Object, łącznie z Arrays i Functions). 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 Objectzawiera 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 thiszmienną ustawioną na wartość, z Objectktó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 thisnie 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 newkluczowe

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 newsłowa kluczowego.

  1. Wywołanie funkcji ze newsłowem kluczowym natychmiast zainicjowałoby Objecttyp type Person.
  2. Konstruktor this Objectma swój konstruktor ustawiony na Person. Zwróć też uwagę, typeof awalże powróci Objecttylko.
  3. Ten nowy Objectmiałby przypisany prototyp Person.prototype. Oznacza to, że każda metoda lub właściwość w Personprototypie byłaby dostępna dla wszystkich wystąpień Person, w tym awal.
  4. Sama funkcja Personjest teraz wywoływana; thisbędący odniesieniem do nowo powstałego obiektu awal.

Całkiem proste, co?

Zauważ, że oficjalna specyfikacja ECMAScript nigdzie nie stwierdza, że ​​tego typu funkcje są rzeczywistymi constructorfunkcjami. Są to zwykłe funkcje i newmoż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: calliapply

Więc tak, ponieważ functions 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 calli apply, a obie mogą być używane do manipulowania wartością thisfunkcji, 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 thisfunkcję foojako odniesienie do thisArg. Wszystkie inne parametry przekazywane do funkcji callsą przekazywane do funkcji foojako 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 thisw dowolnej funkcji.

applyjest prawie tym samym, co callakceptuj, że przyjmuje tylko dwa parametry: thisArgi tablicę zawierającą argumenty, które mają być przekazane do funkcji. Więc powyższe callwezwanie można przetłumaczyć applytak:

foo.apply(thisArg, [1,2,3])

Zauważ, że calli applymoże przesłonić wartość thiswywołania metody set by dot, które omówiliśmy w drugim punkcie. Wystarczająco proste :)

Przedstawiając .... bind!

bindjest bratem calli apply. Jest to również metoda dziedziczona przez wszystkie funkcje z Functionkonstruktora globalnego w JavaScript. Różnica między bindi call/ applypolega na tym, że oba calli applyfaktycznie wywołają funkcję. bindz drugiej strony zwraca nową funkcję z ustawieniem thisArgi 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 calli apply, bindrównież przesłaniają wartość thisustawioną przez wywołanie metody kropkowej.

Należy również zauważyć, że żadna z tych trzech funkcji nie zmienia oryginalnej funkcji. calli applyzwróci wartość ze świeżo skonstruowanych funkcji, podczas gdy bindzwróci świeżo skonstruowaną funkcję, gotową do wywołania.

Dodatkowe rzeczy, skopiuj to

Czasami nie podoba ci się fakt, że thiszmienia 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ść thiszmieniła się wraz z zakresem zagnieżdżonym, ale chcieliśmy, aby wartość była thisz oryginalnego zakresu. Więc „skopiowane” thisdo thati użyty zamiast kopiować this. Sprytne, co?

Indeks:

  1. Co jest przetrzymywane thisdomyślnie?
  2. A co by było, gdybyśmy wywołali tę funkcję jako metodę z notacją Object-dot?
  3. A jeśli użyjemy newsłowa kluczowego?
  4. Jak manipulujemy thisz calli apply?
  5. Korzystanie bind.
  6. Kopiowanie w thiscelu rozwiązania problemów z zakresem zagnieżdżonym.
49 arunjitsingh Jun 27 2010 at 21:10

„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

18 carlodurso Oct 30 2014 at 10:58

Odkąd pojawił się ten wątek, zebrałem kilka punktów dla nowych czytelników this.

Jaka jest wartość thisdeterminacji?

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 windowobiekcie. Dlatego thisw funkcji globalnej odnosi się do windowobiektu globalnego (i ma taką wartość) .

Kiedy use strict, thisw globalnym iw anonimowych funkcji, które nie są zobowiązane do dowolnego obiektu posiada wartość undefined.

Słowo thiskluczowe jest najbardziej niezrozumiane, gdy: 1) pożyczamy metodę, która używa this, 2) przypisujemy metodę, która używa thisdo zmiennej, 3) funkcja, która używa, thisjest przekazywana jako funkcja zwrotna i 4) thisjest używana wewnątrz domknięcia - funkcja wewnętrzna. (2)

Co przyniesie przyszłość

Zdefiniowane w ECMA Script 6 , funkcje strzałkowe przejmują thispowią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 thismechanizm na rzecz szerzej rozumianego zakresu leksykalnego. (1)


Bibliografia:

  1. this & Object Prototypes , autorstwa Kyle'a Simpsona. © 2014 Getify Solutions.
  2. javascriptissexy.com - http://goo.gl/pvl0GX
  3. Angus Croll - http://goo.gl/Z2RacU
18 Seph Oct 07 2013 at 02:46

thisw 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;

thisodwoł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 thisbędzie odnosić się do obiektu okna.

15 blockhead Jun 27 2010 at 20:15

Każdy kontekst wykonania w javascript ma ten parametr, który jest ustawiany przez:

  1. Jak wywoływana jest funkcja (w tym jako metoda obiektu, użycie wywołania i zastosowanie , użycie nowego )
  2. Korzystanie z wiązania
  3. Leksykalnie dla funkcji strzałkowych (przyjmują to z zewnętrznego kontekstu wykonania)
  4. Czy kod jest w trybie ścisłym czy nieścisłym
  5. Czy kod został wywołany przy użyciu eval

Możesz ustawić wartość tego za pomocą func.call, func.applylub 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.

11 ArmanMcHitarian Apr 23 2013 at 19:57

Daniel, niesamowite wyjaśnienie! Kilka słów na ten temat i dobra lista thiswskaźników kontekstu wykonania w przypadku obsługi zdarzeń.

W dwóch słowach, thisw 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)">
11 zangw Nov 29 2015 at 13:01

Oto jedno dobre źródło thisw JavaScript.

Oto podsumowanie:

  • to globalne

    W przeglądarce w zakresie globalnym thisjest to windowobiekt

    <script type="text/javascript">
      console.log(this === window); // true
      var foo = "bar";
      console.log(this.foo); // "bar"
      console.log(window.foo); // "bar"
    

    W przypadku nodekorzystania z repl, thisjest to najwyższa przestrzeń nazw. Możesz odnieść się do tego jako global.

    >this
      { ArrayBuffer: [Function: ArrayBuffer],
        Int8Array: { [Function: Int8Array] BYTES_PER_ELEMENT: 1 },
        Uint8Array: { [Function: Uint8Array] BYTES_PER_ELEMENT: 1 },
        ...
    >global === this
     true
    

    Podczas nodewykonywania ze skryptu, thisw 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 thisArgpodano a (patrz poniżej), zarówno w węźle, jak iw przeglądarce używającej thisfunkcji, która nie jest wywoływana z newodwoł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 thisbę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 newtym thisbę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ą prototypewł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 prototypewł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ć thisw 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 thisjest 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 bindkontekst

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, thisznajduje 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ć, evalaby 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ć, withaby dodać thisdo bieżącego zakresu, aby odczytywać i zapisywać w wartościach thisbez thisjawnego 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 thisodwoł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>
9 ArupHore Jan 31 2017 at 15:29

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:

  1. Globalny (tj. Poza wszystkimi funkcjami)
  2. Wewnętrzne bezpośrednie wywołanie „funkcji niezwiązanej” (tj. Funkcja, która nie została powiązana przez wywołanie functionName.bind )
  3. Wewnątrz pośrednia „funkcja niezwiązana” Wywołaj przez functionName.call i functionName.apply
  4. Wewnątrz wywołania „Bound Function” (tj. Funkcji, która została powiązana przez wywołanie functionName.bind )
  5. Podczas tworzenia obiektów przez „nowy”
  6. Wewnątrz modułu obsługi zdarzeń DOM Inline

Poniżej opisano kolejno każdy z tych kontekstów:

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

  6. 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ł

  1. W kontekście globalnym „to” zawsze odnosi się do „okna” obiektu

  2. 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.

  3. Wartość „this” w funkcji niezwiązanej jest odniesieniem do obiektu, w kontekście którego funkcja jest wywoływana ( „bieżący obiekt” )

  4. Wartość „this” w funkcji niezwiązanej może zostać zastąpiona przez wywołanie i zastosowanie metod funkcji.

  5. Wartość „this” jest ustalona dla funkcji Bound i nie może być zastąpiona przez wywołanie i zastosowanie metod funkcji.

  6. Wiązanie i już powiązana funkcja nie zmienia wartości „this”. Pozostaje ustawiona jako wartość ustawiona przez pierwszą funkcję wiązania.

  7. Wartość „this” w konstruktorze to obiekt, który jest tworzony i inicjowany

  8. Wartość „this” w wbudowanej procedurze obsługi zdarzeń DOM jest odniesieniem do elementu, dla którego podano procedurę obsługi zdarzeń.

9 DmitriPavlutin Nov 08 2016 at 19:17

Prawdopodobnie najbardziej szczegółowy i wyczerpujący artykuł na temat thisjest następujący:

Delikatne wyjaśnienie słowa kluczowego „this” w JavaScript

Pomysł thispolega na zrozumieniu, że typy wywołań funkcji mają istotne znaczenie przy ustawianiu thiswartości.


Mając kłopoty z identyfikacją this, nie zadawaj sobie pytań:

Skąd thispochodzi ?

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 thisktórym zdefiniowano funkcję strzałki ?

Ten sposób myślenia jest właściwy, gdy thismasz do czynienia z bólem głowy i uchroni Cię przed bólem głowy.

7 JamesDrinkard Jul 13 2016 at 02:03

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:

  1. Kiedy przekazujemy metodę (która używa this ) jako argument, który ma być użyty jako funkcja zwrotna.
  2. 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.
  3. 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.
  4. 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.

6 Nipuna Aug 09 2014 at 16:22

thisjest jedną z niezrozumiałych koncepcji w JavaScript, ponieważ zachowuje się trochę inaczej w zależności od miejsca. Po prostu thisodnosi się do „właściciela” funkcji, którą aktualnie wykonujemy .

thispomaga 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 thisjest 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 thismoż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 thisna 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. Personjest wywoływana i thisjest 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 newsłowo kluczowe, whatIsThisodsyła do najbardziej globalnego kontekstu, jaki może znaleźć ( window)

Z obsługą zdarzeń

Jeśli program obsługi zdarzeń jest wbudowany, thisodwoł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 thismoduł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
6 mrmaclean89 Sep 17 2017 at 05:11

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;
5 Trombe Jul 03 2017 at 17:07

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.

4 SimonGroenewolt Jun 27 2010 at 20:15

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)

3 unclexo Jul 25 2018 at 14:04

Trochę informacji o tym słowie kluczowym

Zalogujmy thissł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 exportsto tylko odniesienie domodule.exports

1 PRADEEPSINGHChundawat Apr 06 2016 at 14:15

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

1 gman Jan 29 2019 at 01:37

Mam inne podejście thisdo 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ę, thisjest 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, thisbę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 thisfunkcjonować.

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.bJavaScript najpierw sprawdza obiekt, do którego odwołuje się bezpośrednio awłaściwość b. Jeśli bnie 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 classsłowo kluczowe. Na potrzeby tego thisjednak nie ma to znaczenia. Liczy się to, że gdy szuka w obiekcie awłaściwości, bjeśli znajdzie właściwość bna obiekcie lub w jego łańcuchu prototypów, jeśli bkończy się to funkcją, obowiązują te same zasady, co powyżej. bOdwołania do funkcji zostaną wywołane przy użyciu callmetody i przekazane ajako objectForThis, jak pokazano na początku tej odpowiedzi.

Teraz. Wyobraźmy sobie, że tworzymy funkcję, która jawnie ustawia thisprzed 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 barfunkcji, którą wywołujemy, fooale jawnie przekazaliśmy inny obiekt dla objectForThis, więc kiedy dochodzimy do foo, thisjest ten obiekt wewnętrzny.

To jest to, co skutecznie robią obie bindi =>funkcje. Są bardziej syntaktycznym cukrem. Skutecznie budują nową niewidoczną funkcję, dokładnie tak jak barpowyżej, która jawnie ustawia, thiszanim wywoła jakąkolwiek określoną funkcję. W przypadku bind thisjest 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.bindnie 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, objectForThisale w przeciwieństwie binddo obiektu, który ma być powiązany, jest niejawna. To wszystko, co thisdzieje 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 foobędzie wiązał objsię 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 fooutworzona. Ta niewidoczna funkcja ignoruje thisprzekazane do niej dane i przekazuje objjako 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);
WillemvanderVeen Aug 22 2018 at 00:12

Podsumowanie thisJavaScript:

  • Wartość thisjest określana przez to, w jaki sposób funkcja jest wywoływana, a nie gdzie została utworzona!
  • Zwykle wartość thisjest określana przez obiekt, który znajduje się na lewo od kropki. ( windoww przestrzeni globalnej)
  • W detektorach zdarzeń wartość thisodnosi się do elementu DOM, na którym zdarzenie zostało wywołane.
  • Gdy funkcja in function jest wywoływana ze newsłowem kluczowym, wartość thisodnosi się do nowo utworzonego obiektu
  • Można manipulować wartość thisz 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.

Lord May 20 2020 at 16:43

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:

Wynik jest taki sam, ponieważ zarejestrowaliśmy zmienną „ta” 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 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?