Wie funktioniert das Schlüsselwort "this"?


1309

Ich habe festgestellt, dass es anscheinend keine klare Erklärung dafür gibt, was das thisSchlüsselwort ist und wie es in JavaScript auf der Stack Overflow-Site korrekt (und falsch) verwendet wird.

Ich habe ein sehr seltsames Verhalten damit gesehen und nicht verstanden, warum es aufgetreten ist.

Wie funktioniert thisund wann sollte es verwendet werden?


6
Ich fand dies, als ich "this" quirksmode.org/js/this.html
Wai Wong


2
Peter Michaux plädiert gegen die Verwendung von this peter.michaux.ca/articles/javascript-widgets-without-this
Marcel Korpel

1
Die MDN Übersicht ist nicht halb schlecht ... developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/...
dat

2
Eine interessante Erklärung des thisSchlüsselworts: rainsoft.io/gentle-explanation-of-this-in-javascript
Dmitri Pavlutin

Antworten:


1350

Ich empfehle , zuerst den Artikel Scope von Mike West in JavaScript ( Spiegel ) zu lesen . Es ist eine hervorragende, freundliche Einführung in die Konzepte thisund Umfangsketten von JavaScript.

Sobald Sie sich daran gewöhnt haben, thissind die Regeln eigentlich ziemlich einfach. Der ECMAScript 5.1 Standard definiert this:

§11.1.1 Das thisSchlüsselwort

Das thisSchlüsselwort ergibt den Wert von ThisBinding des aktuellen Ausführungskontexts

Diese Bindung wird vom JavaScript-Interpreter beibehalten, wenn er JavaScript-Code auswertet, wie z. B. ein spezielles CPU-Register, das einen Verweis auf ein Objekt enthält. Der Interpreter aktualisiert die ThisBinding, wenn in einem von nur drei verschiedenen Fällen ein Ausführungskontext eingerichtet wird:

1. Anfänglicher globaler Ausführungskontext

Dies ist der Fall bei JavaScript-Code, der auf oberster Ebene ausgewertet wird, z. B. direkt in einem <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>

Bei der Auswertung von Code im anfänglichen globalen Ausführungskontext wird ThisBinding auf das globale Objekt festgelegt window( §10.4.1.1 ).

Eval-Code eingeben

  • eval() Wird durch einen direkten Aufruf von ThisBinding unverändert gelassen; Es ist der gleiche Wert wie ThisBinding des aufrufenden Ausführungskontexts ( §10.4.2 (2) (a)).

  • … Wenn nicht durch einen direkten Aufruf von eval()
    ThisBinding, wird das globale Objekt so eingestellt, als würde es im anfänglichen globalen Ausführungskontext ausgeführt ( §10.4.2 (1)).

§15.1.2.1.1 definiert, was ein direkter Anruf eval()ist. Grundsätzlich eval(...)handelt es sich um einen direkten Anruf, während etwas wie (0, eval)(...)oder var indirectEval = eval; indirectEval(...);ein indirekter Anruf ist eval(). Siehe Chuckjs Antwort auf (1, eval) ('this') vs eval ('this') in JavaScript? und Dmitry Soshnikovs ECMA-262-5 im Detail. Kapitel 2. Strenger Modus. für den Fall, dass Sie einen indirekten eval()Anruf verwenden könnten .

Funktionscode eingeben

Dies tritt beim Aufrufen einer Funktion auf. Wenn eine Funktion für ein Objekt aufgerufen wird, z. B. in obj.myMethod()oder ein gleichwertiges Objekt, wird obj["myMethod"]()ThisBinding auf das Objekt gesetzt ( objim Beispiel; §13.2.1 ). In den meisten anderen Fällen wird ThisBinding auf das globale Objekt festgelegt ( §10.4.3 ).

Der Grund für das Schreiben "in den meisten anderen Fällen" liegt darin, dass acht integrierte ECMAScript 5-Funktionen vorhanden sind, mit denen ThisBinding in der Argumentliste angegeben werden kann. Diese Sonderfunktionen haben eine sogenannte Funktion, thisArgdie beim Aufruf der Funktion zur ThisBinding wird ( §10.4.3 ).

Diese speziellen integrierten Funktionen sind:

  • 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 ] )

Bei den Function.prototypeFunktionen werden sie für ein Funktionsobjekt aufgerufen, aber anstatt ThisBinding auf das Funktionsobjekt zu setzen, wird ThisBinding auf das gesetzt thisArg.

Bei den Array.prototypeFunktionen wird das callbackfnAngegebene in einem Ausführungskontext aufgerufen, in dem ThisBinding auf gesetzt ist, thisArgfalls angegeben. Andernfalls zum globalen Objekt.

Dies sind die Regeln für einfaches JavaScript. Wenn Sie anfangen, JavaScript-Bibliotheken (z. B. jQuery) zu verwenden, stellen Sie möglicherweise fest, dass bestimmte Bibliotheksfunktionen den Wert von manipulieren this. Die Entwickler dieser JavaScript-Bibliotheken tun dies, weil sie in der Regel die häufigsten Anwendungsfälle unterstützen und Benutzer der Bibliothek dieses Verhalten normalerweise als bequemer empfinden. Wenn Sie Rückruffunktionen übergeben, die thisauf Bibliotheksfunktionen verweisen, sollten Sie in der Dokumentation nach Garantien suchen, welchen Wert der Wert beim thisAufrufen der Funktion hat.

Wenn Sie sich fragen, wie eine JavaScript-Bibliothek den Wert von manipuliert this, verwendet die Bibliothek einfach eine der integrierten JavaScript-Funktionen, die a akzeptieren thisArg. Sie können auch Ihre eigene Funktion mit einer Rückruffunktion schreiben und thisArg:

function doWork(callbackfn, thisArg) {
    //...
    if (callbackfn != null) callbackfn.call(thisArg);
}

Es gibt einen Sonderfall, den ich noch nicht erwähnt habe. Beim Erstellen eines neuen Objekts über den newOperator erstellt der JavaScript-Interpreter ein neues, leeres Objekt, legt einige interne Eigenschaften fest und ruft dann die Konstruktorfunktion für das neue Objekt auf. Wenn also eine Funktion in einem Konstruktorkontext aufgerufen wird, ist der Wert von thisdas neue Objekt, das der Interpreter erstellt hat:

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

Pfeilfunktionen

Pfeil Funktionen (eingeführt in ECMA6) verändern den Umfang this. Siehe die vorhandene kanonische Frage, Pfeilfunktion vs. Funktionsdeklaration / Ausdrücke: Sind sie äquivalent / austauschbar? für mehr Informationen. Aber kurz gesagt:

Pfeilfunktionen haben keine eigene this.... Bindung. Stattdessen werden diese Bezeichner wie jede andere Variable im lexikalischen Bereich aufgelöst. Das bedeutet, dass sich innerhalb einer Pfeilfunktion this... auf die Werte thisin der Umgebung beziehen, in der die Pfeilfunktion definiert ist.

Testen Sie Ihr Verständnis nur zum Spaß anhand einiger Beispiele

Bewegen Sie den Mauszeiger über die hellgrauen Kästchen, um die Antworten anzuzeigen.

  1. Was ist der Wert thisan der markierten Linie? Warum?

    window - Die markierte Zeile wird im anfänglichen globalen Ausführungskontext ausgewertet.

    if (true) {
        // What is `this` here?
    }
  2. Was ist der Wert thisan der markierten Zeile, wenn obj.staticFunction()ausgeführt wird? Warum?

    obj - Beim Aufrufen einer Funktion für ein Objekt wird ThisBinding auf das Objekt festgelegt.

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

  3. Was ist der Wert thisan der markierten Linie? Warum?

    window

    In diesem Beispiel gibt der JavaScript-Interpreter Funktionscode ein, aber weil myFun / obj.myMethodfür ein Objekt nicht aufgerufen wird, wird ThisBinding auf gesetzt window.

    Dies unterscheidet sich von Python, bei dem beim Zugriff auf eine Methode ( obj.myMethod) ein gebundenes Methodenobjekt erstellt wird .

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

  4. Was ist der Wert thisan der markierten Linie? Warum?

    window

    Dieser war schwierig. Bei der Auswertung des Eval-Codes thisist obj. Im Eval-Code wird myFunjedoch kein Objekt aufgerufen, sodass ThisBinding windowfür den Aufruf festgelegt ist.

    function myFun() {
        return this; // What is `this` here?
    }
    var obj = {
        myMethod: function () {
            eval("myFun()");
        }
    };
  5. Was ist der Wert thisan der markierten Linie? Warum?

    obj

    Die Zeile myFun.call(obj);ruft die spezielle integrierte Funktion auf Function.prototype.call(), die thisArgals erstes Argument akzeptiert wird .

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


6
@Ali: Sie beziehen sich auf Abschnitte in Ausgabe 5.1 des ECMAScript-Standards, ECMA-262 . Ich stelle sie zur Verfügung, damit Sie den Standard für die technischen Details lesen können, wenn Sie möchten.
Daniel Trebbien

1
Ich denke, @supertonsky hat Recht mit # 2 - wenn myFun () aus dem globalen Bereich aufgerufen wird und nicht als Methode für das Objekt, wird "dies" das globale Objekt sein, daher ist die Formulierung der Frage wichtig. btw - ich wirklich wie die Idee der Mouseover mit der Antwort für so etwas zu bekommen.
user655489

2
Aber jsfiddle.net/H4LYm/2 zeigt, dass das setTimeoutBeispiel ein thisvon hat window(global).
Kevin Meredith

2
Wenn man aus Python kommt, kann man sich vorstellen, wie frustriert ich war, als ich auf das dritte Beispiel stieß. smh
Marius Mucenicu

1
Diese Antwort sollte wahrscheinlich aktualisiert werden, um die Realität von ES2020 widerzuspiegeln, auch wenn die Änderungen nur terminologisch sind.
Ben Aston

156

Das thisSchlüsselwort verhält sich in JavaScript anders als in anderen Sprachen. In objektorientierten Sprachen thisbezieht sich das Schlüsselwort auf die aktuelle Instanz der Klasse. In JavaScript wird der Wert von thisdurch den Aufrufkontext der Funktion bestimmt (context.function() ) bestimmt und wo er aufgerufen wird.

1. Bei Verwendung im globalen Kontext

Wenn Sie thisim globalen Kontext verwenden, ist es an ein globales Objekt gebunden ( windowim Browser).

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

Wenn Sie thisinnerhalb einer im globalen Kontext definierten Funktion verwenden, thisist diese weiterhin an ein globales Objekt gebunden, da die Funktion tatsächlich zu einer Methode des globalen Kontexts gemacht wird.

function f1()
{
   return this;
}
document.write(f1());  //[object Window]

Oben f1ist eine Methode des globalen Objekts gemacht. Daher können wir es auf windowObjekt auch wie folgt aufrufen :

function f()
{
    return this;
}

document.write(window.f()); //[object Window]

2. Bei Verwendung innerhalb der Objektmethode

Wenn Sie ein thisSchlüsselwort in einer Objektmethode verwenden, thiswird es an das "unmittelbare" umschließende Objekt gebunden.

var obj = {
    name: "obj",
    f: function () {
        return this + ":" + this.name;
    }
};
document.write(obj.f());  //[object Object]:obj

Oben habe ich das Wort sofort in doppelte Anführungszeichen gesetzt. Es ist darauf hinzuweisen, dass, wenn Sie das Objekt in einem anderen Objekt verschachteln, thises an das unmittelbare übergeordnete Objekt gebunden ist.

var obj = {
    name: "obj1",
    nestedobj: {
        name:"nestedobj",
        f: function () {
            return this + ":" + this.name;
        }
    }            
}

document.write(obj.nestedobj.f()); //[object Object]:nestedobj

Selbst wenn Sie dem Objekt eine Funktion explizit als Methode hinzufügen, folgt es den obigen Regeln, dh es zeigt thisimmer noch auf das unmittelbare übergeordnete Objekt.

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. Beim Aufrufen der kontextlosen Funktion

Wenn Sie eine thisInside-Funktion verwenden, die ohne Kontext aufgerufen wird (dh nicht für ein Objekt), ist sie an das globale Objekt ( windowim Browser) gebunden (auch wenn die Funktion innerhalb des Objekts definiert ist).

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 

Ich versuche alles mit Funktionen

Wir können die obigen Punkte auch mit Funktionen ausprobieren. Es gibt jedoch einige Unterschiede.

  • Oben haben wir Objekte mit Objektliteralnotation zu Elementen hinzugefügt. Wir können Mitglieder zu Funktionen hinzufügen, indem wir verwendenthis . um sie zu spezifizieren.
  • Die Objektliteralnotation erstellt eine Instanz eines Objekts, die wir sofort verwenden können. Mit function müssen wir möglicherweise zuerst die Instanz mit erstellennew Operator .
  • Auch in einem Objektliteralansatz können wir bereits definierten Objekten mithilfe des Punktoperators explizit Elemente hinzufügen. Dies wird nur der spezifischen Instanz hinzugefügt. Ich habe dem Funktionsprototyp jedoch eine Variable hinzugefügt, damit sie in allen Instanzen der Funktion wiedergegeben wird.

Unten habe ich alle Dinge ausprobiert, die wir mit Object und thishöher gemacht haben, aber indem ich zuerst eine Funktion erstellt habe, anstatt ein Objekt direkt zu schreiben.

/********************************************************************* 
  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. Bei Verwendung innerhalb der Konstruktorfunktion .

Wenn die Funktion als Konstruktor verwendet wird (dh wenn sie mit einem newSchlüsselwort aufgerufen wird ), zeigt der thisFunktionskörper innerhalb des Funktionskörpers auf das neu erstellte Objekt.

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. Bei Verwendung innerhalb der in der Prototypenkette definierten Funktion

Wenn sich die Methode in der Prototypenkette eines Objekts befindet, thisbezieht sich diese Methode auf das Objekt, für das die Methode aufgerufen wurde, als ob die Methode für das Objekt definiert wäre.

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. Wenden Sie in call () die Funktionen apply () und bind () an

  • Alle diese Methoden sind am definiert Function.prototype .
  • Mit diesen Methoden können Sie eine Funktion einmal schreiben und in einem anderen Kontext aufrufen. Mit anderen Worten, sie ermöglichen es, den Wert anzugeben, der thisverwendet wird, während die Funktion ausgeführt wird. Sie übernehmen auch alle Parameter, die beim Aufrufen an die ursprüngliche Funktion übergeben werden.
  • fun.apply(obj1 [, argsArray])Legt obj1den Wert von thisinside fest fun()und ruft fun()übergebende Elemente argsArrayals Argumente auf.
  • fun.call(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])- Sets obj1als der Wert von thisinnen fun()und Anrufen fun()vorbei arg1, arg2, arg3, ...als Argumente.
  • fun.bind(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])- Gibt den Verweis auf die Funktion zurück, funwobei der thisinnere Spaß an obj1und die Parameter funan die angegebenen Parameter gebunden sindarg1, arg2, arg3,... .
  • Inzwischen ist der Unterschied zwischen apply, callund bindmüssen offensichtlich geworden sind. applyErmöglicht die Angabe der Argumente, die als Array-ähnliches Objekt fungieren sollen, dh ein Objekt mit einer numerischen lengthEigenschaft und entsprechenden nicht negativen ganzzahligen Eigenschaften. Während callermöglicht direkt die Argumente der Funktion zu spezifizieren. Beide applyund callrufen sofort die Funktion im angegebenen Kontext und mit den angegebenen Argumenten auf. Gibt andererseits bindeinfach die an den angegebenen thisWert und die Argumente gebundene Funktion zurück . Wir können den Verweis auf diese zurückgegebene Funktion erfassen, indem wir ihn einer Variablen zuweisen, und später können wir ihn jederzeit aufrufen.
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. thisInside Event Handler

  • Wenn Sie Ereignishandlern eines Elements eine Funktion direkt zuweisen, thisbezieht sich die Verwendung der Funktion zur direkten Behandlung innerhalb des Ereignisses auf das entsprechende Element. Eine solche direkte Funktionszuweisung kann unter Verwendung einer addeventListenerMethode oder durch herkömmliche Ereignisregistrierungsmethoden wie erfolgen onclick.
  • Wenn Sie thisdirekt innerhalb der Ereigniseigenschaft (wie <button onclick="...this..." >) des Elements verwenden, bezieht sich dies auf das Element.
  • Die Verwendung von thisindirekt über die andere Funktion, die innerhalb der Ereignisbehandlungsfunktion oder der Ereigniseigenschaft aufgerufen wird, wird jedoch in das globale Objekt aufgelöst window.
  • Das gleiche obige Verhalten wird erreicht, wenn wir die Funktion mithilfe der Microsoft-Modellmethode für die Ereignisregistrierung an den Ereignishandler anhängen attachEvent. Anstatt die Funktion dem Ereignishandler zuzuweisen (und damit die Funktionsmethode des Elements zu erstellen), ruft sie die Funktion für das Ereignis auf (ruft sie effektiv im globalen Kontext auf).

Ich empfehle, dies besser in JSFiddle zu versuchen .

<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. thisin der ES6-Pfeilfunktion

In einer Pfeilfunktion thisverhält es sich wie allgemeine Variablen: Es wird von seinem lexikalischen Bereich geerbt. Die Funktion this, in der die Pfeilfunktion definiert ist, ist die Pfeilfunktionthis .

Das ist also das gleiche Verhalten wie:

(function(){}).bind(this)

Siehe folgenden Code:

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 

"Wenn Sie dies in einer im globalen Kontext definierten Funktion verwenden, ist dies immer noch an ein globales Objekt gebunden, da die Funktion tatsächlich zu einer Methode des globalen Kontexts gemacht wird." ist falsch. Dies wird dadurch festgelegt, wie eine Funktion aufgerufen wird oder durch Binden , nicht durch den Ort, an dem sie definiert ist. Wenn Sie eine Funktion ohne Basisreferenz ("Kontext") aufrufen, wird dies standardmäßig auf das globale Objekt angewendet oder bleibt im strengen Modus undefiniert.
RobG

@RobG hmm mag sein, aber ich habe dies auf MDN gefunden : In diesem Fall wird der Wert von thisnicht durch den Aufruf festgelegt. Da sich der Code nicht im strengen Modus befindet, muss der Wert von thisimmer ein Objekt sein, sodass standardmäßig das globale Objekt verwendet wird. Und in der Tat dachte ich deshalb, wir könnten direkt anrufen window.f1(), so dass das Mittel f1()bereits an das windowObjekt gebunden ist, meine ich vor dem Aufruf. Verstehe ich es falsch?
Mahesha999

Ich war zu kommentieren (vielleicht nicht klar) auf die Einstellung der Verknüpfung dieses mit „die Funktion tatsächlich ein Verfahren zum globalen Kontext gemacht wird“, als ob es eine Art genannt ist window.fn, was es nicht ist. Dies ist standardmäßig das globale Objekt, da im Aufruf keine Basisreferenz verwendet wurde, nicht aufgrund der Definition der Funktion ( dies wird also immer noch durch den Aufruf der Funktion festgelegt ). Wenn Sie es explizit mit aufrufen window.fn, setzen Sie dies auf window . Gleiches Ergebnis, andere Vorgehensweise. :-)
RobG

"Oben habe ich das Wort sofort gesetzt ..." Nein, hast du nicht. Können Sie dies bitte überarbeiten, damit der Fehler behoben wird? Die Antwort scheint semantisch zu sein, und daher kann ich nicht weiterlesen, bis der Fehler behoben ist, aus Angst, etwas Falsches zu lernen.
TylerH

@ TylerH do Strg + F auf dieser Seite in Ihrem Browser, um Zeichenfolge "sofort" zu finden (einschließlich doppelter Anführungszeichen) Ich denke, es ist da, wenn ich Sie falsch verstehe
Mahesha999

64

Javascript this

Einfacher Funktionsaufruf

Betrachten Sie die folgende Funktion:

function foo() {
    console.log("bar");
    console.log(this);
}
foo(); // calling the function

Beachten Sie, dass wir dies im normalen Modus ausführen, dh der strikte Modus wird nicht verwendet.

Wenn Sie in einem Browser ausgeführt werden, wird der Wert von thisals protokolliert window. Das ist weilwindow es sich um die globale Variable im Bereich eines Webbrowsers handelt.

Wenn Sie denselben Code in einer Umgebung wie node.js ausführen, this auf die globale Variable in Ihrer App verwiesen.

Wenn wir dies nun im strengen Modus ausführen, indem wir die Anweisung "use strict";am Anfang der Funktionsdeklaration hinzufügen , thiswird in keiner der Umgebungen mehr auf die globale Variable verwiesen. Dies geschieht, um Verwirrungen im strengen Modus zu vermeiden. thiswürde in diesem Fall einfach protokollierenundefined , da dies nicht definiert ist.

In den folgenden Fällen würden wir sehen, wie der Wert von manipuliert wird this .

Aufruf einer Funktion für ein Objekt

Es gibt verschiedene Möglichkeiten, dies zu tun. Wenn Sie native Methoden in Javascript wie forEachund aufgerufen haben slice, sollten Sie bereits wissen, dass sich die thisVariable in diesem Fall auf die bezieht, Objectauf die Sie diese Funktion aufgerufen haben (Beachten Sie, dass in Javascript fast alles ein ist Object, einschließlich Arrays und Functions). Nehmen Sie zum Beispiel den folgenden Code.

var myObj = {key: "Obj"};
myObj.logThis = function () {
    // I am a method
    console.log(this);
}
myObj.logThis(); // myObj is logged

Wenn a Objecteine Eigenschaft enthält, die a enthält Function, wird die Eigenschaft als Methode bezeichnet. Wenn diese Methode aufgerufen wird, wird ihre thisVariable immer auf die Variable gesetzt, der Objectsie zugeordnet ist. Dies gilt sowohl für strenge als auch für nicht strenge Modi.

Beachten Sie, dass der Verweis auf thisin der neuen Variablen nicht mehr beibehalten wird , wenn eine Methode in einer anderen Variablen gespeichert (oder vielmehr kopiert) wird. Zum Beispiel:

// continuing with the previous code snippet

var myVar = myObj.logThis;
myVar();
// logs either of window/global/undefined based on mode of operation

Betrachtet man ein allgemeineres praktisches Szenario:

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

Das newSchlüsselwort

Betrachten Sie eine Konstruktorfunktion in 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`

Wie funktioniert das? Mal sehen, was passiert, wenn wir das newSchlüsselwort verwenden.

  1. Das Aufrufen der Funktion mit dem newSchlüsselwort würde sofort einen ObjectTyp initialisieren Person.
  2. Für den Konstruktor Objectist der Konstruktor festgelegt Person. Beachten Sie auch, dass typeof awalzurückkehren würde Objectnur.
  3. Diesem neuen Objectwürde der Prototyp von zugewiesen Person.prototype. Dies bedeutet, dass jede Methode oder Eigenschaft im PersonPrototyp für alle Instanzen von verfügbar ist Person, einschließlich awal.
  4. Die Funktion Personselbst wird jetzt aufgerufen. thiseine Referenz auf das neu konstruierte Objekt sein awal.

Ziemlich einfach, oder?

Beachten Sie, dass die offizielle ECMAScript-Spezifikation nirgends besagt, dass solche Arten von Funktionen tatsächliche constructorFunktionen sind. Sie sind nur normale Funktionen und newkönnen für jede Funktion verwendet werden. Es ist nur so, dass wir sie als solche verwenden und sie daher nur als solche bezeichnen.

Funktionen für Funktionen aufrufen: call undapply

Also ja, da functionsind es auchObjects (und tatsächlich erstklassige Variablen in Javascript) sind, haben sogar Funktionen Methoden, die ... nun, Funktionen selbst sind.

Alle Funktionen erben vom Globalen Function, und zwei seiner vielen Methoden sind callund apply, und beide können verwendet werden, um den Wert von thisin der Funktion zu manipulieren, für die sie aufgerufen werden.

function foo () { console.log (this, arguments); }
var thisArg = {myObj: "is cool"};
foo.call(thisArg, 1, 2, 3);

Dies ist ein typisches Beispiel für die Verwendung call. Es nimmt grundsätzlich den ersten Parameter und setzt thisin der Funktion fooals Referenz auf thisArg. Alle anderen übergebenen Parameter callwerden fooals Argumente an die Funktion übergeben .
Der obige Code meldet sich also {myObj: "is cool"}, [1, 2, 3]in der Konsole an. Ziemlich schöne Möglichkeit, den Wert von zu ändernthis einer Funktion .

applyist fast dasselbe wie zu callakzeptieren, dass nur zwei Parameter benötigt werden: thisArgund ein Array, das die Argumente enthält, die an die Funktion übergeben werden sollen. Der obige callAufruf kann also folgendermaßen übersetzt werden apply:

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

Beachten Sie, dass callund applyden Wert von überschreiben kannthis Aufrufs der durch die Punktmethode festgelegten Menge wir im zweiten Aufzählungszeichen erörtert haben. Einfach genug :)

Präsentieren .... bind !

bindist ein Bruder von callund apply. Es ist auch eine Methode, die von allen Funktionen des globalen FunctionKonstruktors in Javascript geerbt wird . Der Unterschied zwischen bindund call/ applybesteht darin, dass beide callund applydie Funktion tatsächlich aufrufen. bindGibt andererseits eine neue Funktion mit der Voreinstellung thisArgund zurück arguments. Nehmen wir ein Beispiel, um dies besser zu verstehen:

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]`

Sehen Sie den Unterschied zwischen den drei? Es ist subtil, aber sie werden unterschiedlich verwendet. Wie callund apply, bindauch over-ride den Wertthis Satz von Punkt-Methodenaufruf.

Beachten Sie auch, dass keine dieser drei Funktionen Änderungen an der ursprünglichen Funktion vornimmt. callund applywürde den Wert von frisch konstruierten Funktionen während zurückgebenbind die frisch konstruierte Funktion selbst zurückgegeben wird, die zum Aufrufen bereit ist.

Zusätzliches Zeug, kopiere das

Manchmal gefällt Ihnen die Tatsache nicht, dass sich thisÄnderungen mit dem Bereich ändern, insbesondere der verschachtelte Bereich. Schauen Sie sich das folgende Beispiel an.

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

Im obigen Code sehen wir, dass sich der Wert von thismit dem verschachtelten Bereich geändert hat, aber wir wollten den Wert von thisvom ursprünglichen Bereich. Also wir ‚kopiert‘ thisauf thatund verwendet kopieren die statt this. Clever, was?

Index:

  1. Was ist thisstandardmäßig enthalten?
  2. Was ist, wenn wir die Funktion als Methode mit Objekt-Punkt-Notation aufrufen?
  3. Was ist, wenn wir die verwenden new Schlüsselwort verwenden?
  4. Wie manipulieren wir thismit callund apply?
  5. Verwenden von bind.
  6. Kopieren, thisum Probleme mit verschachtelten Bereichen zu lösen.

47

"das" dreht sich alles um Umfang. Jede Funktion hat ihren eigenen Bereich, und da alles in JS ein Objekt ist, kann sogar eine Funktion mit "this" einige Werte in sich speichern. OOP 101 lehrt, dass "dies" nur für Instanzen gilt eines Objekts gilt. Daher hat jedes Mal, wenn eine Funktion ausgeführt wird, eine neue "Instanz" dieser Funktion eine neue Bedeutung von "dies".

Die meisten Menschen sind verwirrt, wenn sie versuchen, "dies" in anonymen Schließfunktionen wie:

(Funktion (Wert) {
    this.value = value;
    $ ('. some-elements'). each (function (elt) {
        elt.innerHTML = this.value; // uh oh !! möglicherweise undefiniert
    });
}) (2);

Hier in jedem () enthält "this" also nicht den "Wert", den Sie erwarten (von

this.value = value;
über). Um dieses Problem zu lösen (kein Wortspiel beabsichtigt), könnte ein Entwickler:

(Funktion (Wert) {
    var self = this; // kleine Veränderung
    self.value = value;
    $ ('. some-elements'). each (function (elt) {
        elt.innerHTML = self.value; // Puh !! == 2
    });
}) (2);

Versuch es; Sie werden anfangen, dieses Programmiermuster zu mögen


6
"Alles in JS ist ein Objekt" ist nicht wahr, JavaScript hat auch primitive Werte, siehe bclary.com/2004/11/07/#a-4.3.2
Marcel Korpel

6
Die primitiven Werte scheinen einige Methoden für sich zu haben, wie String # substring (), Number # toString () usw. Also, vielleicht nicht mit der gleichen Nomenklatur wie dieser Artikel, verhalten sie sich wirklich so, als wären sie Objekte (sie sind es) Alle Prototypen, dh String # substring (), sind wirklich: String.prototype.substring = function () {...}). Bitte korrigieren Sie mich, wenn ich falsch liege.
Arunjitsingh

12
Das thisSchlüsselwort hat nichts mit dem Gültigkeitsbereich zu tun. Es hat auch eine Bedeutung auch in Funktionen, die keine Eigenschaften von Objekten sind.
Bergi

1
@ arunjitsingh - dazu gibt es zwei Denkschulen. Ich mag die, die sagt " alles ist ein Objekt, aber einige können der Einfachheit halber durch Primitive dargestellt werden ". ;-)
RobG

9
thisgeht es nicht nur um Umfang. Es geht ALLES um den Ausführungskontext, der nicht mit dem Bereich identisch ist. JavaScript hat einen lexikalischen Gültigkeitsbereich (dh der Gültigkeitsbereich wird durch die Position des Codes bestimmt), wird jedoch davon thisbestimmt, wie die Funktion, die ihn enthält, aufgerufen wird - nicht davon, wo sich diese Funktion befindet.
Scott Marcus

16

Da dieser Thread aufgetaucht ist, habe ich einige Punkte für Leser zusammengestellt, die neu im thisThema sind.

Wie wird der Wert von thisbestimmt?

Wir verwenden dies ähnlich wie wir Pronomen in natürlichen Sprachen wie Englisch verwenden: „John rennt schnell, weil er versucht, den Zug zu erreichen.“ Stattdessen hätten wir schreiben können: „… John versucht, den Zug zu erreichen“.

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 wird erst dann ein Wert zugewiesen, wenn ein Objekt die Funktion aufruft, in der es definiert ist. Im globalen Bereich werden alle globalen Variablen und Funktionen für das windowObjekt definiert . Daher thisbezieht sich eine globale Funktion auf das globale windowObjekt (und hat dessen Wert) .

Wenn use strict, thisdie gebunden sind , nicht auf jedes Objekt in der globalen und in anonymen Funktionen enthält einen Wert von undefined.

Das thisSchlüsselwort wird am häufigsten missverstanden, wenn: 1) wir eine verwendete Methode ausleihen this, 2) thiseiner Variablen eine verwendete Methode zuweisen , 3) eine verwendete Funktion thisals Rückruffunktion übergeben wird und 4) thisinnerhalb eines Abschlusses verwendet wird - eine innere Funktion. (2)

Tabelle

Was hält die Zukunft

In ECMA Script 6 definiert , übernehmen Pfeilfunktionen die thisBindung aus dem umschließenden (funktionalen oder globalen) Bereich.

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!

Während Pfeilfunktionen eine Alternative zur Verwendung darstellen bind(), ist es wichtig zu beachten, dass sie im Wesentlichen den traditionellen thisMechanismus zugunsten eines allgemeineren lexikalischen Geltungsbereichs deaktivieren . (1)


Verweise:

  1. this & Object Prototypes von Kyle Simpson. © 2014 Getify Solutions.
  2. javascriptissexy.com - http://goo.gl/pvl0GX
  3. Angus Croll - http://goo.gl/Z2RacU

16

thisbezieht sich in JavaScript immer auf den 'Eigentümer' der Funktion, die ausgeführt wird .

Wenn kein expliziter Eigentümer definiert ist, wird auf den obersten Eigentümer, das Fensterobjekt, verwiesen.

Also wenn ich es täte

function someKindOfFunction() {
   this.style = 'foo';
}

element.onclick = someKindOfFunction;

thiswürde sich auf das Elementobjekt beziehen. Aber seien Sie vorsichtig, viele Leute machen diesen Fehler.

<element onclick="someKindOfFunction()">

Im letzteren Fall verweisen Sie lediglich auf die Funktion und übergeben sie nicht an das Element. Daher thiswird auf das Fensterobjekt verwiesen.


15

Jeder Ausführungskontext in Javascript hat einen diesen Parameter, der durch festgelegt ist:

  1. Wie die Funktion aufgerufen wird (einschließlich als Objektmethode, Verwendung von Aufruf und Anwendung , Verwendung von Neu )
  2. Verwendung von binden
  3. Lexikalisch für Pfeilfunktionen (sie übernehmen das Dies ihres äußeren Ausführungskontexts)
  4. Gibt an, ob sich der Code im strengen oder im nicht strengen Modus befindet
  5. Ob der Code mit aufgerufen wurde eval

Sie können den Wert festgelegt dies mit func.call, func.applyoder func.bind.

Standardmäßig und was die meisten Anfänger verwirrt, wenn ein Listener aufgerufen wird, nachdem ein Ereignis für ein DOM-Element ausgelöst wurde, ist dies Wert der Funktion das DOM-Element.

Mit jQuery ist es trivial, dies mit jQuery.proxy zu ändern.


9
Es ist ein wenig mehr richtig zu sagen , dass jede Funktion Aufruf einen Umfang hat. Mit anderen Worten, was thisin Javascript verwirrend ist, ist, dass es keine intrinsische Eigenschaft der Funktion selbst ist, sondern ein Artefakt der Art und Weise, wie die Funktion aufgerufen wird.
Pointy

@pointy danke. Was in js am meisten Verwirrung stiftet, ist die Tatsache, dass in allen zuvor verwendeten Sprachen (c #, c ++) - dies nicht manipuliert werden kann n immer auf die Objektinstanz verweist, während es in js davon abhängt und beim Aufrufen geändert werden kann Funktionen func.call, func.bindusw. - Sushil
Sushil

2
thisverweist nicht auf den Funktionsumfang einer Funktion. thisverweist auf ein bestimmtes Objekt (oder möglicherweise undefined), das, wie Sie gesagt haben, mit .call()oder geändert werden kann .apply(). Der Gültigkeitsbereich einer Funktion ist (im Wesentlichen vereinfacht), auf welche Variablen sie Zugriff hat. Dies hängt ganz davon ab, wo die Funktion deklariert ist und nicht geändert werden kann.
nnnnnn

@Pointy: "Es ist etwas korrekter zu sagen, dass jeder Funktionsaufruf einen Bereich hat." Noch mehr richtig zu sagen , dass die Funktionen (und jetzt Blöcke) haben Umfang , Funktionsaufrufe haben Kontext . Bereich definiert die Bezeichner, die von Code in diesem Bereich verwendet werden können. Der Kontext definiert, an was diese Bezeichner gebunden sind.
TJ Crowder

1
"Was auch immer dieser Bereich ist, wird mit" dies "bezeichnet." Nein, thisund Umfang haben in ES5 und früher überhaupt nichts miteinander zu tun (z. B. als diese Antwort geschrieben wurde). In ES2015 (auch bekannt als ES6) thisund Bereich sind eine relativ minimale Beziehung zwischen Pfeilfunktionen (die Funktion thisin einem Pfeil wird von ihrem umschließenden Bereich übernommen), thisbezieht sich jedoch niemals auf einen Bereich.
TJ Crowder

10

Hier ist eine gute Quelle von thisin JavaScript.

Hier ist die Zusammenfassung:

  • global dies

    In einem Browser ist im globalen Bereich thisdas windowObjekt

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

    Bei der nodeVerwendung von repl thisist dies der oberste Namespace. Sie können es als bezeichnen global.

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

    Bei der nodeAusführung von einem Skript aus thisbeginnt der globale Bereich als leeres Objekt. Es ist nicht dasselbe wieglobal

    \\test.js
    console.log(this);  \\ {}
    console.log(this === global); \\ fasle
  • Funktion dies

Außer im Fall von DOM-Ereignishandlern oder wenn a thisArgbereitgestellt wird (siehe weiter unten), verwenden sowohl im Knoten als auch in einem Browser thisin einer Funktion, die nicht mit newVerweisen aufgerufen wird, den globalen Bereich…

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

Wenn Sie verwenden use strict;, wird in diesem Fall thisseinundefined

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

Wenn Sie eine Funktion aufrufen, bei newder thises sich um einen neuen Kontext handelt, verweist sie nicht auf den globalen Kontext 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 dieses

Von Ihnen erstellte Funktionen werden zu Funktionsobjekten. Sie erhalten automatisch eine spezielle prototypeEigenschaft, der Sie Werte zuweisen können. Wenn Sie eine Instanz erstellen, indem Sie Ihre Funktion mit aufrufen, erhalten newSie Zugriff auf die Werte, die Sie der prototypeEigenschaft zugewiesen haben . Sie greifen mit auf diese Werte zu this.

function Thing() {
  console.log(this.foo);
}

Thing.prototype.foo = "bar";

var thing = new Thing(); //logs "bar"
console.log(thing.foo);  //logs "bar"

Es ist normalerweise ein Fehler, Arrays oder Objekte auf dem zuzuweisen prototype. Wenn Sie möchten, dass Instanzen jeweils ihre eigenen Arrays haben, erstellen Sie sie in der Funktion und nicht im Prototyp.

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 []
  • Einwände dagegen

Sie können thisin jeder Funktion eines Objekts auf andere Eigenschaften dieses Objekts verweisen. Dies ist nicht dasselbe wie eine Instanz, die mit erstellt wurde new.

var obj = {
    foo: "bar",
    logFoo: function () {
        console.log(this.foo);
    }
};

obj.logFoo(); //logs "bar"
  • DOM Event dies

In einem HTML-DOM-Ereignishandler thiswird immer auf das DOM-Element verwiesen, an das das Ereignis angehängt wurde

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

Es sei denn, Sie bindden Kontext

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 dies

In HTML-Attributen, in die Sie JavaScript einfügen können, thisbefindet sich ein Verweis auf das Element.

<div id="foo" onclick="console.log(this);"></div>
<script type="text/javascript">
document.getElementById("foo").click(); //logs <div id="foo"...
</script>
  • bewerte dies

Sie können verwenden, evalum darauf zuzugreifen this.

function Thing () {
}
Thing.prototype.foo = "bar";
Thing.prototype.logFoo = function () {
    eval("console.log(this.foo)"); //logs "bar"
}

var thing = new Thing();
thing.logFoo();
  • mit diesem

Sie können den aktuellen Bereich zum Lesen und Schreiben von Werten withhinzufügen this, thisohne thisexplizit darauf zu verweisen .

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"
  • jQuery this

Die jQuery wird an vielen Stellen thisauf ein DOM-Element verweisen.

<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

Daniel, tolle Erklärung! Ein paar Worte dazu und eine gute Liste von thisAusführungskontextzeigern für Event-Handler.

Mit zwei Worten, thisin JavaScript zeigt das Objekt, von dem (oder von dessen Ausführungskontext) die aktuelle Funktion ausgeführt wurde, und es ist immer schreibgeschützt. Sie können es trotzdem nicht festlegen (ein solcher Versuch führt zu 'Ungültige linke Hand') Seite in Zuweisung 'Nachricht.

Für Ereignishandler: Inline-Ereignishandler, z. B. <element onclick="foo">überschreiben Sie alle anderen Handler, die zuvor und zuvor angehängt wurden. Seien Sie also vorsichtig und vermeiden Sie die Inline-Ereignisdelegierung. Und danke an Zara Alaverdyan, die mich durch eine abweichende Debatte zu dieser Liste von Beispielen inspiriert hat :)

  • 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)">

9

Es gibt viel Verwirrung darüber, wie "dies" Schlüsselwort in JavaScript interpretiert wird. Hoffentlich legt dieser Artikel alle ein für alle Mal zur Ruhe. Und vieles mehr. Bitte lesen Sie den gesamten Artikel sorgfältig durch. Seien Sie gewarnt, dass dieser Artikel lang ist.

Unabhängig vom Kontext, in dem es verwendet wird, verweist "this" immer auf das "aktuelle Objekt" in Javascript. Was das "aktuelle Objekt" ist, unterscheidet sich jedoch je nach Kontext . Der Kontext kann genau 1 der 6 folgenden sein:

  1. Global (dh außerhalb aller Funktionen)
  2. Inside Direct-Aufruf "Non Bound Function" (dh eine Funktion, die nicht durch Aufrufen von functionName.bind gebunden wurde )
  3. Inside Indirect "Non Bound Function" Aufruf über functionName.call und functionName.apply
  4. Innerhalb des Aufrufs "Gebundene Funktion" (dh eine Funktion, die durch Aufrufen von functionName.bind gebunden wurde )
  5. Während der Objekterstellung durch "neu"
  6. Inside Inline DOM-Ereignishandler

Im Folgenden wird jeder dieser Kontexte einzeln beschrieben:

  1. Globaler Kontext (dh außerhalb aller Funktionen):

    Außerhalb aller Funktionen (dh im globalen Kontext) ist das "aktuelle Objekt" (und damit der Wert von "this" ) immer das "Fenster" -Objekt für Browser.

  2. Inside Direct-Aufruf "Non Bound Function" :

    Innerhalb eines direkten Aufrufs "Nicht gebundene Funktion" wird das Objekt, das den Funktionsaufruf aufgerufen hat, zum "aktuellen Objekt" (und damit zum Wert von "this" ). Wenn eine Funktion ohne explizites aktuelles Objekt aufgerufen wird , ist das aktuelle Objekt entweder das "Fenster" -Objekt (für den nicht strengen Modus) oder undefiniert (für den strengen Modus). Jede im globalen Kontext definierte Funktion (oder Variable) wird automatisch zu einer Eigenschaft des "Fenster" -Objekts. Zum Beispiel wird angenommen, dass die Funktion im globalen Kontext als definiert ist

    function UserDefinedFunction(){
        alert(this)
        }

    Es wird zur Eigenschaft des Fensterobjekts, als hätten Sie es als definiert

    window.UserDefinedFunction=function(){
      alert(this)
    }  

    Wenn Sie diese Funktion im "nicht strengen Modus" direkt über "UserDefinedFunction ()" aufrufen / aufrufen, wird sie automatisch als "window.UserDefinedFunction ()" aufgerufen / aufgerufen und "window" zum "aktuellen Objekt" (und damit zum Wert von "). this " ) in " UserDefinedFunction ". Wenn Sie diese Funktion im" Non Strict Mode "aufrufen, wird Folgendes ausgeführt

    UserDefinedFunction() // displays [object Window]  as it automatically gets invoked as window.UserDefinedFunction()

    Wenn Sie im "Strict Mode" die Funktion direkt über "UserDefinedFunction ()" aufrufen / aufrufen, wird sie "NOT" automatisch als "window.UserDefinedFunction ()" aufrufen / aufrufen. Daher das "aktuelle Objekt" (und der Wert von "this"). ) innerhalb von "UserDefinedFunction" muss undefiniert sein . Das Aufrufen dieser Funktion im "Strict Mode" führt zu Folgendem

    UserDefinedFunction() // displays undefined

    Das explizite Aufrufen mit dem Fensterobjekt führt jedoch zu Folgendem

    window.UserDefinedFunction() // "always displays [object Window]   irrespective of mode."

    Schauen wir uns ein anderes Beispiel an. Bitte schauen Sie sich den folgenden Code an

     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

    Im obigen Beispiel sehen wir, dass, wenn "UserDefinedFunction" über o1 aufgerufen wurde , "this" den Wert o1 annimmt und der Wert seiner Eigenschaften "a" und "b" angezeigt wird. Der Wert von "c" und "d" wurde als undefiniert angezeigt, da o1 diese Eigenschaften nicht definiert

    Ähnlich , wenn „UserDefinedFunction“ wurde durch aufgerufen o2 , „this“ Wert nimmt o2 und den Wert seiner Eigenschaften „c“ und „d“ displayed.The Wert erhalten „a“ und „b“ wurden , wie gezeigt nicht definiert , wie o2 tut diese Eigenschaften nicht definieren.

  3. Inside Indirect "Non Bound Function" Aufruf über functionName.call und functionName.apply :

    Wenn eine "nicht gebundene Funktion" über functionName.call oder functionName.apply aufgerufen wird , wird das "aktuelle Objekt" (und damit der Wert von "this" ) auf den Wert des Parameters "this" (erster Parameter) gesetzt, der an den Aufruf übergeben wird Ich bewerbe mich . Der folgende Code zeigt dasselbe.

    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

    Der obige Code zeigt deutlich, dass der Wert "this" für jede "NON Bound Function" durch Aufruf / Anwenden geändert werden kann . Wenn der Parameter "this" nicht explizit an call / apply übergeben wird , wird "current object" (und damit der Wert von "this") im nicht strengen Modus auf "window" und im strengen Modus auf "undefined" gesetzt .

  4. Innerhalb des Aufrufs "Gebundene Funktion" (dh einer Funktion, die durch Aufrufen von functionName.bind gebunden wurde ):

    Eine gebundene Funktion ist eine Funktion, deren "dieser" Wert festgelegt wurde. Der folgende Code demonstrierte, wie "dies" bei gebundener Funktion funktioniert

    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

    Wie im obigen Code angegeben, kann "dieser" Wert für eine "gebundene Funktion" NICHT durch Aufrufen / Anwenden geändert werden . Wenn der Parameter "this" nicht explizit an bind übergeben wird, wird "current object" (und damit der Wert von "this" ) im nicht strengen Modus auf "window" und im strengen Modus auf "undefined" gesetzt . Eine Sache noch. Das Binden einer bereits gebundenen Funktion ändert den Wert von "this" nicht . Es bleibt als der von der ersten Bindungsfunktion festgelegte Wert festgelegt.

  5. Während der Objekterstellung durch "neu" :

    Innerhalb einer Konstruktorfunktion verweist das "aktuelle Objekt" (und damit der Wert von "this" ) auf das Objekt, das derzeit durch "new" erstellt wird, unabhängig vom Bindungsstatus der Funktion. Wenn der Konstruktor jedoch eine gebundene Funktion ist, wird er mit vordefinierten Argumenten aufgerufen, die für die gebundene Funktion festgelegt sind.

  6. Inside Inline DOM-Ereignishandler :

    Bitte schauen Sie sich das folgende HTML-Snippet an

    <button onclick='this.style.color=white'>Hello World</button>
    <div style='width:100px;height:100px;' onclick='OnDivClick(event,this)'>Hello World</div>

    Das "das" in den obigen Beispielen bezieht sich auf das "button" -Element bzw. das "div" -Element.

    Im ersten Beispiel muss die Schriftfarbe der Schaltfläche beim Klicken auf Weiß gesetzt werden.

    Im zweiten Beispiel wird beim Klicken auf das Element "div" die Funktion OnDivClick aufgerufen , wobei der zweite Parameter auf das angeklickte Element div verweist. Der Wert von "this" in OnDivClick darf jedoch NICHT auf das angeklickte div- Element verweisen . Es muss als "Fensterobjekt" oder "undefiniert" im nicht strengen bzw. strengen Modus festgelegt werden (wenn OnDivClick eine ungebundene Funktion ist ) oder auf einen vordefinierten gebundenen Wert festgelegt werden (wenn OnDivClick eine gebundene Funktion ist ).

Das Folgende fasst den gesamten Artikel zusammen

  1. Im globalen Kontext bezieht sich "dies" immer auf das "Fenster" -Objekt

  2. Wenn eine Funktion aufgerufen wird, wird sie im Kontext eines Objekts ( "aktuelles Objekt" ) aufgerufen . Wenn das aktuelle Objekt nicht explizit angegeben wird, ist das aktuelle Objekt standardmäßig das "Fensterobjekt" im NICHT-Strict-Modus und "Undefiniert" im Strict-Modus.

  3. Der Wert von "this" innerhalb einer nicht gebundenen Funktion ist die Referenz auf ein Objekt, in dessen Kontext die Funktion aufgerufen wird ( "aktuelles Objekt" ).

  4. Der Wert von "this" innerhalb einer nicht gebundenen Funktion kann durch Aufrufen und Anwenden von Methoden der Funktion überschrieben werden .

  5. Der Wert von "this" ist für eine gebundene Funktion festgelegt und kann nicht durch Aufrufen und Anwenden von Methoden der Funktion überschrieben werden .

  6. Die bindende und bereits gebundene Funktion ändert den Wert von "this" nicht. Es bleibt als der von der ersten Bindungsfunktion festgelegte Wert festgelegt.

  7. Der Wert von "this" innerhalb eines Konstruktors ist das Objekt, das erstellt und initialisiert wird

  8. Der Wert "this" in einem Inline-DOM-Ereignishandler bezieht sich auf das Element, für das der Ereignishandler angegeben ist.


9

Wahrscheinlich der ausführlichste und umfassendste Artikel über this ist der folgende:

Schonende Erklärung dieses Schlüsselworts in JavaScript

Die Idee dahinter thisist zu verstehen, dass die Funktionsaufruftypen die signifikante Bedeutung für die Einstellung des thisWerts haben.


Wenn mit Schwierigkeiten zu identifizieren this, nicht sich fragen:

Woher kommt thises ?

aber Sie fragen Sie sich:

Wie wird die Funktion aufgerufen ?

Für eine Pfeilfunktion (Sonderfall der Kontexttransparenz) fragen Sie sich:

Welchen Wert hat thiswo die Pfeilfunktion definiert ist ?

Diese Einstellung ist richtig im Umgang mit thisund erspart Ihnen Kopfschmerzen.


Vielleicht können Sie nicht nur auf Ihr Blog verlinken, sondern auch etwas genauer untersuchen, wie das Stellen dieser Fragen jemandem hilft, das thisKeyword zu verstehen .
Magnus Lind Oxlund

7

Dies ist die beste Erklärung , die ich gesehen habe: Verstehen Sie JavaScripts diese mit Clarity

Die diese Referenz bezieht sich immer auf (und hält den Wert von) ein objekt einer singuläres objekt und es in der Regel in einer Funktion , oder ein Verfahren verwendet wird, obwohl es außerhalb einer Funktion im globalen Bereich verwendet werden kann. Beachten Sie, dass der strikte Modus in globalen Funktionen und in anonymen Funktionen, die an kein Objekt gebunden sind, den Wert undefined enthält.

Es gibt vier Szenarien, in denen dies verwirrend sein kann:

  1. Wenn wir ein Verfahren (das verwendet passieren diese ) als Argument als Callback - Funktion verwendet werden.
  2. Wenn wir eine innere Funktion (einen Verschluss) verwenden. Es ist wichtig zu beachten, dass Closures mit dem Schlüsselwort this nicht auf diese Variable der äußeren Funktion zugreifen können, da auf diese Variable nur von der Funktion selbst zugegriffen werden kann, nicht von inneren Funktionen.
  3. Wenn ein Verfahren , das auf beruht dies auf eine Variable in Kontexten zugeordnet, in welchem Fall diese Verweise eine andere Aufgabe , als ursprünglich beabsichtigt.
  4. Wenn Sie dies zusammen mit den Methoden bind, apply und call verwenden.

Er gibt Codebeispiele, Erklärungen und Lösungen, die ich für sehr hilfreich hielt.


6

In pseudoklassischen Begriffen ist die Art und Weise, wie viele Vorlesungen das Schlüsselwort 'this' lehren, ein Objekt, das von einer Klasse oder einem Objektkonstruktor instanziiert wird. Stellen Sie sich jedes Mal vor, wenn ein neues Objekt aus einer Klasse erstellt wird, dass unter der Haube eine lokale Instanz eines 'this'-Objekts erstellt und zurückgegeben wird. Ich erinnere mich, dass es so gelehrt wurde:

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

thisist eines der missverstandenen Konzepte in JavaScript, da es sich von Ort zu Ort kaum anders verhält. thisBezieht sich einfach auf den "Eigentümer" der Funktion, die wir gerade ausführen .

thishilft dabei, das aktuelle Objekt (auch als Ausführungskontext bezeichnet) abzurufen, mit dem wir arbeiten. Wenn Sie verstehen, in welchem ​​Objekt die aktuelle Funktion ausgeführt wird, können Sie leicht verstehen, was aktuell thisist

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

Oben erstellen wir 3 Variablen mit dem gleichen Namen 'val'. Eine im globalen Kontext, eine innerhalb von obj und die andere innerhalb von innerMethod of obj. JavaScript löst Bezeichner in einem bestimmten Kontext auf, indem die Bereichskette von local go global nach oben verschoben wird.


Nur wenige Orte, an denen thisunterschieden werden kann

Aufrufen einer Methode eines Objekts

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

Wenn line1 ausgeführt wird, erstellt JavaScript einen Ausführungskontext (EC) für den Funktionsaufruf und setzt thisauf das Objekt , auf das vor dem letzten "" verwiesen wird. . In der letzten Zeile können Sie also verstehen, dass dies a()im globalen Kontext ausgeführt wurdewindow .

Mit Konstruktor

this kann verwendet werden, um auf das zu erstellende Objekt zu verweisen

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

Wenn neu Person()ausgeführt wird, wird ein vollständig neues Objekt erstellt. Personheißt und seinthis auf dieses neue Objekt verweisen.

Funktionsaufruf

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 

Wenn das newSchlüsselwort whatIsThisfehlt, wird auf den globalsten Kontext verwiesen, den es finden kann (window )

Mit Event-Handlern

Wenn der Ereignishandler inline ist, thisbezieht er sich auf ein globales Objekt

<script type="application/javascript">
    function click_handler() {
        alert(this); // alerts the window object
    }
</script>

<button id='thebutton' onclick='click_handler()'>Click me!</button>

thisBezieht sich beim Hinzufügen eines Ereignishandlers über JavaScript auf das DOM-Element, das das Ereignis generiert hat.



5

Der Wert von "this" hängt vom "Kontext" ab, in dem die Funktion ausgeführt wird. Der Kontext kann ein beliebiges Objekt oder das globale Objekt sein, dh ein Fenster.

Die Semantik von "dies" unterscheidet sich also von den traditionellen OOP-Sprachen. Und es verursacht Probleme: 1. wenn eine Funktion an eine andere Variable übergeben wird (höchstwahrscheinlich ein Rückruf); und 2. wenn ein Abschluss von einer Mitgliedsmethode einer Klasse aufgerufen wird.

In beiden Fällen ist dies auf Fenster eingestellt.


3

Was würde das helfen? (Die größte Verwirrung von 'dies' in Javascript ist darauf zurückzuführen, dass es im Allgemeinen nicht mit Ihrem Objekt verknüpft ist, sondern mit dem aktuellen Ausführungsbereich - das funktioniert möglicherweise nicht genau so, fühlt sich für mich aber immer so an - eine vollständige Erklärung finden Sie im Artikel.)


1
Es wäre besser zu sagen, dass es " mit dem aktuellen Ausführungskontext " verknüpft ist . Mit Ausnahme von ES6 (Entwurf) ändert sich dies mit Pfeilfunktionen, wo dies im äußeren Ausführungskontext behoben wird.
RobG

3

Ein paar Infos dazu Keyword

Lassen Sie uns das thisSchlüsselwort im globalen Bereich ohne weiteren Code in der Konsole protokollieren

console.log(this)

In Client / Browser ist das this Schlüsselwort ein globales Objektwindow

console.log(this === window) // true

und

In Server / Node / Javascript ist das Laufzeitschlüsselwort this auch ein globales Objektmodule.exports

console.log(this === module.exports) // true
console.log(this === exports) // true

Denken Sie daran, exportsist nur ein Hinweis aufmodule.exports


1

diese Verwendung für Scope einfach so

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

Der Wert von txt1 und txt ist im obigen Beispiel gleich. $ (this) = $ ('# tbleName tbody tr') ist der gleiche


1

Ich habe eine andere Einstellung this als die anderen Antworten, von denen ich hoffe, dass sie hilfreich sind.

Eine Möglichkeit, JavaScript zu betrachten, besteht darin, festzustellen, dass es nur eine Möglichkeit gibt, eine Funktion 1 aufzurufen . Es ist

functionObject.call(objectForThis, arg0, arg1, arg2, ...);

Es wird immer ein Wert angegeben objectForThis.

Alles andere ist syntaktischer Zucker für functionObject.call

Alles andere kann also dadurch beschrieben werden, wie es übersetzt wird functionObject.call.

Wenn Sie nur eine Funktion aufrufen, thisist dies das "globale Objekt", das im Browser das Fenster ist

function foo() {
  console.log(this);
}

foo();  // this is the window object

Mit anderen Worten,

foo();

wurde effektiv übersetzt in

foo.call(window);

Beachten Sie, dass, wenn Sie den strengen Modus verwenden this, dies der Fall istundefined

'use strict';

function foo() {
  console.log(this);
}

foo();  // this is the window object

was bedeutet

Mit anderen Worten,

foo();

wurde effektiv übersetzt in

foo.call(undefined);

In JavaScript gibt es Operatoren wie +und -und *. Es gibt auch den Punktoperator.

Der .Operator bedeutet bei Verwendung mit einer Funktion auf der rechten Seite und einem Objekt auf der linken Seite effektiv "Objekt übergeben als"this Funktion übergeben".

Beispiel

const bar = {
  name: 'bar',
  foo() { 
    console.log(this); 
  },
};

bar.foo();  // this is bar

Mit anderen Worten bar.foo()übersetzt inconst temp = bar.foo; temp.call(bar);

Beachten Sie, dass es keine Rolle spielt, wie die Funktion erstellt wurde (meistens ...). All dies führt zu den gleichen Ergebnissen

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

Auch dies sind alles nur syntaktische Zucker für

{ const temp = bar.fn1; temp.call(bar); }
{ const temp = bar.fn2; temp.call(bar); }
{ const temp = bar.fn3; temp.call(bar); }

Eine weitere Falte ist die Prototypkette. Wenn Sie a.bJavaScript verwenden, wird zuerst das Objekt überprüft, auf das direkt afür die Eigenschaft verwiesen wird b. Wenn bdas Objekt nicht gefunden wird, sucht JavaScript im Prototyp des Objekts nach b.

Es gibt verschiedene Möglichkeiten, den Prototyp eines Objekts zu definieren. Am häufigsten wird 2019 das classSchlüsselwort verwendet. Für die Zwecke, thisobwohl es keine Rolle spielt. Was zählt, ist, dass, wenn es im Objekt anach Eigenschaften sucht, bwenn es Eigenschaften bauf dem Objekt findet, oder in seiner Prototypkette, wenn bes eine Funktion ist, dieselben Regeln wie oben gelten. Die Funktionsreferenzen bwerden mit der callMethode aufgerufen und übergebena als objectForThis übergeben, wie oben in dieser Antwort gezeigt.

Jetzt. Stellen wir uns vor, wir erstellen eine Funktion, die explizit festgelegt wird, thisbevor eine andere Funktion aufgerufen wird, und rufen sie dann mit dem .Operator (Punkt) auf

function foo() {
  console.log(this);
}

function bar() {
  const objectForThis = {name: 'moo'}
  foo.call(objectForThis);  // explicitly passing objectForThis
}

const obj = {
  bar,
};

obj.bar();  

Im Anschluss an die Übersetzung Gebrauch call, obj.bar()wird const temp = obj.bar; temp.call(obj);. Wenn wir die barFunktion eingeben, die wir aufrufen, fooaber explizit ein anderes Objekt für objectForThis übergeben, wenn wir bei foo ankommenthis ist dies das innere Objekt.

Dies ist, was beide bindund =>Funktionen effektiv tun. Sie sind mehr syntaktischer Zucker. Sie erstellen effektiv eine neue unsichtbare Funktion genau wie baroben, die explizit festgelegt wird, thisbevor die angegebene Funktion aufgerufen wird. Im Falle von bind thiswird auf alles gesetzt, an das Sie übergeben 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'});

Beachten Sie, dass functionObject.bindwir , wenn es nicht existiert, unsere eigenen so machen könnten

function bind(fn, objectForThis) {
  return function(...args) {
    return fn.call(objectForthis, ...args);
  };
}

und dann könnten wir es so nennen

function foo() {
  console.log(this);
}

const bar = bind(foo, {name:'abc'});

Pfeilfunktionen, der =>Operator sind syntaktischer Zucker zum Binden

const a = () => {console.log(this)};

ist das gleiche wie

const tempFn = function() {console.log(this)}; 
const a = tempFn.bind(this);

Ebenso bindwird eine neue unsichtbare Funktion erstellt, die die angegebene Funktion mit einem gebundenen Wert aufruft, für den objectForThisjedoch im Gegensatz zu binddem zu bindenden Objekt implizit ist. Es ist was auch immer thispassiert, wenn die=> Operator verwendet wird.

Also, genau wie die obigen Regeln

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()übersetzt const temp = obj.foo; temp.call(obj);wodurch der Pfeil Operator innerhalb foobinden objan eine neue unsichtbare Funktion und dass neue unsichtbare Funktion zurück , die zugewiesen ist b. b()funktioniert wie immer als b.call(window)oder b.call(undefined)ruft die neue unsichtbare Funktion auf, die fooerstellt wurde. Diese unsichtbare Funktion ignoriert das thisübergebene und wird objals objectForThis` an die Pfeilfunktion übergeben.

Der obige Code übersetzt in

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 ist eine andere ähnliche Funktion wiecall

functionName.apply(objectForThis, arrayOfArgs);

Ab ES6 können Sie dies jedoch konzeptionell sogar in übersetzen

functionName.call(objectForThis, ...arrayOfArgs);

0

Zusammenfassung thisJavascript:

  • Der Wert von thiswird dadurch bestimmt, wie die Funktion nicht aufgerufen wird, wo sie erstellt wurde!
  • Normalerweise wird der Wert von thisdurch das Objekt bestimmt, das vom Punkt übrig bleibt. (window im globalen Raum)
  • Bei Ereignis-Listenern der Wert von this bezieht sich auf das DOM-Element, für das das Ereignis aufgerufen wurde.
  • Wenn in function mit dem newSchlüsselwort der Wert von aufgerufen wirdthis bezieht sich auf das neu erstellte Objekt
  • Sie können den Wert der Manipulation thismit den Funktionen: call, apply,bind

Beispiel:

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
              
             

Beispiel für Ereignis-Listener:

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>

Beispielkonstruktor:

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.


0

Um "dies" richtig zu verstehen, muss man den Kontext, den Umfang und den Unterschied zwischen ihnen verstehen.

Umfang : in JavaScript Umfang ist mit der Sichtbarkeit der Variablen bezogen, Umfang Erzielt durch die Verwendung der Funktion. (Lesen Sie mehr über den Umfang)

Kontext : Der Kontext bezieht sich auf Objekte. Es bezieht sich auf das Objekt, zu dem eine Funktion gehört. Wenn Sie das JavaScript-Schlüsselwort "this" verwenden, bezieht es sich auf das Objekt, zu dem die Funktion gehört. Wenn Sie beispielsweise innerhalb einer Funktion sagen: "this.accoutNumber", beziehen Sie sich auf die Eigenschaft "accoutNumber", die zu dem Objekt gehört, zu dem diese Funktion gehört.

Wenn das Objekt "myObj" eine Methode namens "getMyName" hat und das JavaScript-Schlüsselwort "this" in "getMyName" verwendet wird, verweist es auf "myObj". Wenn die Funktion "getMyName" im globalen Bereich ausgeführt wurde, bezieht sich "this" auf das Fensterobjekt (außer im strengen Modus).

Nun sehen wir uns ein Beispiel an:

    <script>
        console.log('What is this: '+this);
        console.log(this);
    </script>

Das Ausführen von Code in der Browserausgabe wird: Geben Sie hier die Bildbeschreibung ein

Entsprechend der Ausgabe, die Sie sich im Kontext des Fensterobjekts befinden, ist auch sichtbar, dass sich der Fensterprototyp auf das Objekt bezieht.

Versuchen wir es nun innerhalb einer Funktion:

    <script>
        function myFunc(){
            console.log('What is this: '+this);
            console.log(this);
        }
        myFunc();
    </script>

Ausgabe:

Geben Sie hier die Bildbeschreibung ein Die Ausgabe ist dieselbe, da wir 'diese' Variable im globalen Bereich und im Funktionsbereich protokolliert haben. Wir haben den Kontext nicht geändert. In beiden Fällen war der Kontext in Bezug auf das Witwenobjekt derselbe .

Jetzt erstellen wir unser eigenes Objekt. In Javascript können Sie ein Objekt auf viele Arten erstellen.

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

Ausgabe: Geben Sie hier die Bildbeschreibung ein

Aus dem obigen Beispiel haben wir herausgefunden, dass sich das Schlüsselwort 'this' auf einen neuen Kontext bezieht, der mit myObj zusammenhängt, und myObject hat auch eine Prototypkette zu Object.

Lassen Sie uns ein weiteres Beispiel werfen:

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

Ausgabe: Sinn machen, oder? (Kommentare lesen) Geben Sie hier die Bildbeschreibung ein

Wenn Sie Probleme haben, das obige Beispiel zu verstehen, versuchen wir es mit unserem eigenen Rückruf.

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

Ausgabe: Geben Sie hier die Bildbeschreibung ein

Lassen Sie uns nun Scope, Self, IIFE und DIESES Verhalten verstehen

       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> 

Die Ausgabe ist ziemlich großartig, oder? Geben Sie hier die Bildbeschreibung ein


-1

Einfache Antwort:

Das Schlüsselwort "this" hängt immer vom Kontext des Aufrufs ab. Sie werden unten erwähnt.

  1. Die Funktion wird mit einem neuen Schlüsselwort aufgerufen

    Wenn die Funktion mit dem Schlüsselwort NEW aufgerufen wird, wird DIESES an das neu erstellte Objekt gebunden.

    function Car(){
      this.name="BMW";
    }
    const myCar=new Car();
    myCar.name; // output "BMW"

    Oben wird dies an das Objekt 'myCar' gebunden

  2. Die Funktion wird explizit unter Verwendung von Anruf- und Anwendungsmethoden aufgerufen.

    In diesem Fall wird DIESES an das Objekt gebunden, das explizit an die Funktion übergeben wird.

    var obj1={"name":"bond"};
    function printMessage(msg){
        return msg+" "+this.name;
    }
    const message=printMessage.call(obj1,"my name is ");
    console.log(message); //HERE THIS WILL BE BOUND TO obj1 WHICH WE PASSED EXPLICITLY. SAME FOR APPLY METHOD ALSO.
  3. Wenn die Funktion implizit mit dem Objekt aufgerufen wird, ist dies an dieses Objekt gebunden

    var obj1={
       "name":"bond",
        getName: function () {
                    return this.name;
                 }
    };
    const newname=obj1.getName();
    console.log(newname); //HERE THIS WILL BE BOUND TO obj1(WHITCHEVER OBJECT IS MENTIONED BEFORE THE DOT THIS WILL BE BOUND TO THAT)
  4. Wenn die Funktion ohne Kontext aufgerufen wird, ist dies an ein globales Objekt gebunden

    const util = {
       name: 'Utility',
       getName: function () {
                    return this.name;
    };
    
    const getName=util.getName;
    const newName=getName();
    console.log(newName); // IF THIS EXECUTED IN BROWSER THIS WILL BE  BOUND TO WINDOW OBJECT. IF THIS EXECUTED IN SERVER THIS WILL BE BOUND TO GLOBAL OBJECT
  5. Im strengen Modus wird dies nicht definiert

    function setName(name){
        "use strict"
        return this.name;
    }
    setName(); //WILL BE ERROR SAYING name IS UNDEFINED. 
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.