Frage Wie funktioniert das Keyword "this"?


Ich habe bemerkt, dass es keine klare Erklärung dafür zu geben scheint this Schlüsselwort ist und wie es in JavaScript auf der Stack Overflow-Site korrekt (und inkorrekt) verwendet wird.

Ich habe ein sehr merkwürdiges Verhalten mitbekommen und habe nicht verstanden, warum es passiert ist.

Wie geht es? this arbeiten und wann sollte es verwendet werden?


1071
2018-06-27 13:12


Ursprung


Antworten:


Ich empfehle zu lesen Mike West's Artikel Umfang in JavaScript (Spiegel) zuerst. Es ist eine ausgezeichnete, freundliche Einführung in die Konzepte von this und Umfangsketten in JavaScript.

Sobald Sie sich daran gewöhnen thisDie Regeln sind eigentlich ziemlich einfach. Das ECMAScript 5.1 Standard definiert this:

§11.1.1 Das this Stichwort

Das this Das Schlüsselwort wertet den Wert von ThisBinding des aktuellen Ausführungskontexts aus

ThisBinding ist etwas, das der JavaScript-Interpreter beim Auswerten von JavaScript-Code verwaltet, wie ein spezielles CPU-Register, das einen Verweis auf ein Objekt enthält. Der Interpreter aktualisiert die ThisBinding beim Erstellen eines Ausführungskontexts in nur drei Fällen:

1. Erster globaler Ausführungskontext

Dies ist der Fall für JavaScript-Code, der auf der obersten Ebene, z.B. wenn 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>

Wenn ThisBinding Code im globalen Erstausführungskontext auswertet, wird es auf das globale Objekt gesetzt. window (§10.4.1.1).

Eval-Code eingeben

  • ... durch einen direkten Anruf an eval() ThisBinding bleibt unverändert; Es ist derselbe Wert wie ThisBinding des aufrufenden Ausführungskontexts (§10.4.2 (2) (a)).

  • ... wenn nicht durch einen direkten Anruf zu eval()
    ThisBinding wird auf das globale Objekt festgelegt als ob Ausführen im ersten globalen Ausführungskontext (§10.4.2 (1)).

§15.1.2.1.1 definiert, was ein direkter Aufruf an eval() ist. Grundsätzlich gilt, eval(...) ist ein direkter Anruf, während etwas wie (0, eval)(...) oder var indirectEval = eval; indirectEval(...); ist ein indirekter Aufruf an eval(). Sehen Chuckjs Antwort zu (1, eval) ('this') gegen eval ('this') in JavaScript? und Dmitry Soshnikovs ECMA-262-5 im Detail. Kapitel 2. Strenger Modus. für wann Sie eine indirekte verwenden könnten eval() Anruf.

Funktionscode eingeben

Dies tritt auf, wenn eine Funktion aufgerufen wird. Wenn eine Funktion für ein Objekt aufgerufen wird, z. B. in obj.myMethod() oder das Äquivalent obj["myMethod"]()Dann wird ThisBinding auf das Objekt gesetzt (obj im Beispiel; §13.2.1). In den meisten anderen Fällen wird ThisBinding auf das globale Objekt gesetzt (§10.4.3).

Der Grund für das Schreiben "in den meisten anderen Fällen" liegt darin, dass acht ECMAScript 5-Funktionen vorhanden sind, die ThisBinding in der Argumentenliste angeben können. Diese speziellen Funktionen nehmen eine sogenannte thisArg Das wird die ThisBinding beim Aufruf der Funktion (§10.4.3).

Diese speziellen eingebauten 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 ] )

Im Falle der Function.prototype Funktionen werden sie für ein Funktionsobjekt aufgerufen, aber ThisBinding wird nicht auf ThisBinding gesetzt, sondern auf the thisArg.

Im Falle der Array.prototype Funktionen, die gegeben callbackfn wird in einem Ausführungskontext aufgerufen, in dem ThisBinding festgelegt ist thisArg wenn geliefert; andernfalls auf das globale Objekt.

Das sind die Regeln für einfaches JavaScript. Wenn Sie mit der Verwendung von JavaScript-Bibliotheken (z. B. jQuery) beginnen, stellen Sie möglicherweise fest, dass bestimmte Bibliotheksfunktionen den Wert von this. Die Entwickler dieser JavaScript-Bibliotheken tun dies, weil sie dazu neigen, die häufigsten Anwendungsfälle zu unterstützen, und Benutzer der Bibliothek finden dieses Verhalten normalerweise bequemer. Beim Weiterleiten von Callback-Funktionen referenzieren this Zu Bibliotheksfunktionen sollten Sie in der Dokumentation nachlesen, für welche Garantien der Wert von this ist wenn die Funktion aufgerufen wird.

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

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

Es gibt einen speziellen Fall, den ich noch nicht erwähnt habe. Beim Erstellen eines neuen Objekts über die new Der JavaScript-Interpreter erstellt ein neues, leeres Objekt, legt einige interne Eigenschaften fest und ruft dann die Konstruktorfunktion für das neue Objekt auf. Wenn eine Funktion in einem Konstruktorkontext aufgerufen wird, wird daher der Wert von this ist das 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);

Nur zum Spaß, testen Sie Ihr Verständnis mit einigen Beispielen

Um die Antworten zu enthüllen, fahre mit der Maus über die hellgelben Kästen.

  1. Was ist der Wert von? this an der markierten Linie? Warum?

      window - Die markierte Zeile wird im ersten globalen Ausführungskontext ausgewertet.

    if (true) {
        // What is `this` here?
    }
    
  2. Was ist der Wert von? this an der markierten Linie wann obj.staticFunction() wird ausgeführt? Warum?

      obj - Beim Aufruf einer Funktion für ein Objekt wird ThisBinding auf das Objekt gesetzt.

    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 von? this an der markierten Linie? Warum?

      window

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

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

    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 von? this an der markierten Linie? Warum?

      window

    Dieser war schwierig. Bei der Auswertung des Eval-Codes this ist obj. Im Evaluierungscode jedoch myFun wird für ein Objekt nicht aufgerufen, daher wird ThisBinding auf festgelegt window für den Anruf.

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

      obj

    Die Linie myFun.call(obj); ruft die spezielle eingebaute Funktion auf Function.prototype.call(), die akzeptiert thisArg als erstes 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);
      


1150
2017-07-07 17:32



Das this Das Schlüsselwort verhält sich in JavaScript anders als in anderen Sprachen. In objektorientierten Sprachen kann der this Schlüsselwort bezieht sich auf die aktuelle Instanz der Klasse. In JavaScript der Wert von this wird hauptsächlich durch den Aufrufkontext der Funktion bestimmt (context.function()) und wo es heißt.

1. Wenn im globalen Kontext verwendet

Wenn Sie verwenden this im globalen Kontext ist es an globale Objekte gebunden (windowim Browser)

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

Wenn Sie verwenden this innerhalb einer Funktion, die im globalen Kontext definiert ist, this ist immer noch an das globale Objekt gebunden, da die Funktion tatsächlich zu einer Methode des globalen Kontexts gemacht wird.

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

Über f1 ist eine Methode des globalen Objekts gemacht. So können wir es auch anrufen window Objekt wie folgt:

function f()
{
    return this;
}

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

2. Wenn innerhalb der Objektmethode verwendet

Wenn Sie verwenden this Schlüsselwort innerhalb einer Objektmethode, this ist 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. Wenn Sie das Objekt in ein anderes Objekt verschachteln, dann müssen Sie darauf hinweisen this ist an den unmittelbaren Elternteil gebunden.

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 explizit eine Funktion als Methode hinzufügen, folgt es immer noch den obigen Regeln this zeigt immer noch auf das unmittelbare Elternobjekt.

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 Aufruf einer kontextlosen Funktion

Wenn Sie verwenden this innerhalb der Funktion, die ohne Kontext aufgerufen wird (d. h. nicht für irgendein Objekt), ist sie an das globale Objekt gebunden (window im Browser) (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 

Probieren Sie alles mit Funktionen

Wir können oben Punkte mit Funktionen auch versuchen. Es gibt jedoch einige Unterschiede.

  • Oben haben wir Objekte zu Objekten hinzugefügt, die die Objektliteralnotation verwenden. Wir können Mitglieder zu Funktionen hinzufügen, indem wir verwenden this. um sie zu spezifizieren.
  • Objektliteralnotation erstellt eine Objektinstanz, die wir sofort verwenden können. Mit der Funktion müssen wir möglicherweise zuerst ihre Instanz mit erstellen new Operator.
  • Auch in einem Objekt-Literal-Ansatz können wir Mitglieder mit dem Punktoperator explizit zu bereits definierten Objekten hinzufügen. Dies wird nur der spezifischen Instanz hinzugefügt. Allerdings habe ich dem Funktionsprototyp eine Variable hinzugefügt, so dass sie in allen Instanzen der Funktion berücksichtigt wird.

Unten habe ich all die Dinge ausprobiert, die wir mit Object und this oben, aber zuerst durch Erstellen einer Funktion, anstatt direkt ein Objekt 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. Wenn innerhalb der Konstruktorfunktion verwendet.

Wenn die Funktion als Konstruktor verwendet wird (dh wenn sie mit aufgerufen wird) new Stichwort), this Der innere Funktionskörper zeigt auf das neu konstruierte 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. Wenn innerhalb der Funktion verwendet, die auf der Prototypkette definiert ist

Wenn die Methode in der Prototypkette eines Objekts ist, this Innerhalb einer solchen Methode wird auf das Objekt verwiesen, auf das die Methode angewendet wurde, als ob die Methode auf dem 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. Inside call (), apply () und bind () Funktionen

  • Alle diese Methoden sind definiert auf Function.prototype.
  • Diese Methoden erlauben es, eine Funktion einmal zu schreiben und sie in einem anderen Kontext aufzurufen. Mit anderen Worten erlauben sie, den Wert von anzugeben this welches während der Ausführung der Funktion verwendet wird. Sie übernehmen auch alle Parameter, die beim Aufruf an die ursprüngliche Funktion übergeben werden.
  • fun.apply(obj1 [, argsArray]) Sätze obj1 als der Wert von this Innerhalb fun() und Anrufe fun() vorbeifahrende Elemente von argsArray als seine Argumente.
  • fun.call(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]]) - Sätze obj1 als der Wert von this Innerhalb fun() und Anrufe fun() Vorbeigehen arg1, arg2, arg3, ... als seine Argumente.
  • fun.bind(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]]) - Gibt den Verweis auf die Funktion zurück fun mit thisInnen Spaß gebunden an obj1 und Parameter von fun gebunden an die angegebenen Parameter arg1, arg2, arg3,....
  • Inzwischen ist der Unterschied zwischen apply, call und bind muss offensichtlich geworden sein. apply erlaubt es, die Argumente anzugeben, um als arrayartiges Objekt zu fungieren, d. h. ein Objekt mit einem numerischen Wert length Eigenschaft und entsprechende nicht negative ganzzahlige Eigenschaften. Wohingegen call erlaubt es, die Argumente für die Funktion direkt anzugeben. Beide apply und call ruft sofort die Funktion im angegebenen Kontext und mit den angegebenen Argumenten auf. Andererseits, bind Gibt einfach die Funktion zurück, die an die angegebene gebunden ist this Wert und die Argumente. Wir können den Verweis auf diese zurückgegebene Funktion erfassen, indem wir sie einer Variablen zuweisen, und später können wir sie 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. this in Event-Handlern

  • Wenn Sie Funktionen direkt einem Event-Handler eines Elements zuweisen, verwenden Sie this direkt in der Ereignisbehandlungsfunktion bezieht sich auf das entsprechende Element. Eine solche direkte Funktionszuordnung kann mit Hilfe von erfolgen addeventListener Methode oder durch die traditionellen Ereignisregistrierungsmethoden wie onclick.
  • In ähnlicher Weise, wenn Sie verwenden this direkt in der Event-Eigenschaft (wie <button onclick="...this..." >) des Elements bezieht es sich auf das Element.
  • Jedoch Gebrauch von this indirekt über die andere Funktion, die im Inneren aufgerufen wird, wird die Ereignisbehandlungsfunktion oder die Ereigniseigenschaft in das globale Objekt aufgelöst window.
  • Das gleiche obige Verhalten wird erreicht, wenn wir die Funktion mit der Ereignisregistrierungsmodellmethode von Microsoft an den Ereignishandler anhängen attachEvent. Anstatt die Funktion dem Ereignishandler zuzuordnen (und damit die Funktionsmethode des Elements zu machen), ruft sie die Funktion für das Ereignis auf (effektiv im globalen Kontext aufrufend).

Ich empfehle, dies besser zu versuchen JSFidel.

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

122
2017-10-26 15:07



Javascript ist 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, d. H. Der strikte Modus wird nicht verwendet.

Wenn in einem Browser ausgeführt, der Wert von this würde als geloggt werden window. Das ist weil window ist die globale Variable im Bereich eines Webbrowsers.

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

Nun, wenn wir dies im strikten Modus ausführen, indem wir die Anweisung hinzufügen "use strict"; an den Anfang der Funktionsdeklaration, this würde sich nicht mehr auf die globale Variable in einer der Umgebungen beziehen. Dies geschieht, um Verwechslungen im strikten Modus zu vermeiden. this würde, in diesem Fall nur loggen undefinedweil es so ist, ist es nicht definiert.

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

Eine Funktion für ein Objekt aufrufen

Es gibt verschiedene Möglichkeiten, dies zu tun. Wenn Sie in Javascript native Methoden aufgerufen haben forEach und sliceDu solltest das schon wissen this Variable bezieht sich in diesem Fall auf die Object auf dem Sie diese Funktion aufgerufen haben (Beachten Sie, dass in JavaScript fast alles ein ist Object, einschließlich Arrays und Functions). Nehmen Sie den folgenden Code zum Beispiel.

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

Wenn ein Object enthält eine Eigenschaft, die a enthält FunctionDie Eigenschaft wird als Methode bezeichnet. Diese Methode wird immer aufgerufen, wenn sie aufgerufen wird this Variable auf die gesetzt Object es ist assoziiert mit. Dies gilt sowohl für strikte als auch für nicht strikte Modi.

Beachten Sie, dass, wenn eine Methode in einer anderen Variablen gespeichert (oder besser kopiert) wird, der Verweis auf this wird in der neuen Variable nicht mehr beibehalten. Beispielsweise:

// continuing with the previous code snippet

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

Betrachten wir ein praktischeres 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 new Stichwort

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? Nun, mal sehen, was passiert, wenn wir die new Stichwort.

  1. Aufruf der Funktion mit dem new Schlüsselwort würde sofort ein initialisieren Object vom Typ Person.
  2. Der Konstruktor davon Object hat seinen Konstruktor auf gesetzt Person. Beachten Sie auch das typeof awal würde zurückkehren Object nur.
  3. Das neue Object würde dem Prototyp von zugeordnet werden Person.prototype. Dies bedeutet, dass jede Methode oder Eigenschaft in der Person Prototyp wäre für alle Instanzen verfügbar Person, einschließlich awal.
  4. Die Funktion Person selbst wird jetzt aufgerufen; this eine Referenz auf das neu konstruierte Objekt sein awal.

Ziemlich geradlinig, was?

Beachten Sie, dass in der offiziellen ECMAScript-Spezifikation keine Angabe enthalten ist, dass solche Arten von Funktionen tatsächlich sind constructor Funktionen. Sie sind nur normale Funktionen und new kann für jede Funktion verwendet werden. Es ist nur so, dass wir sie als solche benutzen, und so nennen wir sie nur als solche.

Funktionen auf Funktionen aufrufen: call und apply

Also ja, seit functions sind auch Objects (und in der Tat erste Klassenvariablen in Javascript), sogar Funktionen haben Methoden, die ... nun, funktionieren sie selbst.

Alle Funktionen erben von der globalen Functionund zwei seiner vielen Methoden sind call und apply, und beide können verwendet werden, um den Wert von zu manipulieren this in der Funktion, an der sie aufgerufen werden.

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

Dies ist ein typisches Anwendungsbeispiel call. Es nimmt grundsätzlich den ersten Parameter und die ersten Sätze an this in der Funktion foo als Referenz zu thisArg. Alle anderen Parameter wurden übergeben call werden an die Funktion übergeben foo als Argumente.
Also wird der obige Code protokollieren {myObj: "is cool"}, [1, 2, 3] in der Konsole. Ziemlich nette Weise, den Wert von zu ändern this in irgendeiner Funktion.

apply ist fast das Gleiche wie call akzeptieren, dass es nur zwei Parameter benötigt: thisArg und ein Array, das die Argumente enthält, die an die Funktion übergeben werden sollen. Also das obige call Anruf kann übersetzt werden in apply so was:

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

Beachten Sie, dass call und apply kann den Wert von überschreiben this set by dot Methodenaufruf wir in der zweiten Kugel diskutiert. Einfach genug :)

Präsentieren .... bind!

bind ist ein Bruder von call und apply. Es ist auch eine Methode, die von allen globalen Funktionen übernommen wird Function Konstruktor in Javascript. Der Unterschied zwischen bind und call/apply ist das beides call und apply wird tatsächlich die Funktion aufrufen. bindAuf der anderen Seite gibt eine neue Funktion mit der thisArg und arguments voreingestellt. Nehmen wir ein Beispiel, um das 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]`

Siehst du den Unterschied zwischen den dreien? Es ist subtil, aber sie werden anders verwendet. Mögen call und apply, bind wird auch den Wert von übersteuern this festgelegt durch Dot-Methode Aufruf.

Beachten Sie auch, dass keine dieser drei Funktionen die ursprüngliche Funktion ändert. call und apply würde den Wert von frisch erstellten Funktionen während zurückgeben bind wird die frisch konstruierte Funktion selbst zurückgeben, bereit, angerufen zu werden.

Extra Zeug, kopiere das

Manchmal magst du die Tatsache nicht, dass this Änderungen mit dem Bereich, speziell verschachtelter Bereich. Sehen 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 der Wert von this geändert mit verschachtelten Bereich, aber wir wollten den Wert von this aus dem ursprünglichen Umfang. Also haben wir 'kopiert' this zu that und benutzte die Kopie anstelle von this. Clever, was?

Index:

  1. Was wird festgehalten? this standardmäßig?
  2. Was ist, wenn wir die Funktion als Methode mit Objekt-Punkt-Notation bezeichnen?
  3. Was ist, wenn wir das benutzen? new Stichwort?
  4. Wie manipulieren wir? this mit call und apply?
  5. Verwenden bind.
  6. Kopieren this um verschachtelte Probleme zu lösen.

46
2018-06-27 14:10



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

Die meisten Menschen werden verwirrt, wenn sie versuchen, "das" innerhalb von anonymen Schließfunktionen zu verwenden, wie:

(Funktion (Wert) {
    this.value = Wert;
    $ ('. einige-Elemente'). je (Funktion (elt) {
        elt.innerHTML = this.value; // oh oh oh !! möglicherweise undefiniert
    });
}) (2);

Also hier, in jedem (), hält "dies" nicht den "Wert", von dem Sie es erwarten (von

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

(Funktion (Wert) {
    var selbst = das; // kleine Veränderung
    self.value = Wert;
    $ ('. einige-Elemente'). je (Funktion (elt) {
        elt.innerHTML = self.value; // Puh !! == 2
    });
}) (2);

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


43
2017-10-06 19:46



this in Javascript bezieht sich immer auf den "Besitzer" der Funktion, die ist ausgeführt werden.

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

Also wenn ich es tat

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

element.onclick = someKindOfFunction;

this würde auf das Elementobjekt verweisen. Aber Vorsicht, viele Leute machen diesen Fehler

<element onclick="someKindOfFunction()">

In letzterem Fall verweisen Sie lediglich auf die Funktion, nicht auf das Element. Dafür, this verweist auf das Fensterobjekt.


12
2017-10-30 03:58



Da dieser Thread aufgeplatzt ist, habe ich einige Punkte für Leser neu zusammengestellt this Thema. 

Wie ist der Wert von thisentschlossen?

Wir verwenden das ähnlich wie wir Pronomen in natürlichen Sprachen wie Englisch verwenden: "John läuft schnell, weil er versucht den Zug zu erwischen. "Stattdessen hätten wir schreiben können ... John versucht den Zug zu erwischen ".

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  ist kein Wert zugewiesen bis ein Objekt die Funktion aufruft, wo es definiert ist. Im globalen Gültigkeitsbereich sind alle globalen Variablen und Funktionen definiert window Objekt. Deshalb, this in einer globalen Funktion bezieht sich auf den globalen (und hat den Wert von) window Objekt.

Wann use strict, this In globalen und in anonymen Funktionen, die nicht an ein Objekt gebunden sind, ist ein Wert von undefined.

Das this Stichwort ist am meisten missverstanden wenn: 1) wir eine Methode ausleihen, die verwendet this, 2) weisen wir eine Methode zu, die verwendet this zu einer Variablen, 3) eine Funktion, die verwendet this wird als Callback-Funktion übergeben und 4) this wird innerhalb eines Verschlusses verwendet - eine innere Funktion. (2)

table

Was hält die Zukunft?

Definiert in ECMA-Skript 6Pfeil-Funktionen übernehmen die this Bindung von der umschließender (Funktion oder globaler) 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!

Pfeil-Funktionen bieten eine Alternative zur Verwendung bind()Es ist wichtig zu beachten, dass sie im Wesentlichen das Traditionelle deaktivieren this Mechanismus zugunsten eines allgemeineren lexikalischen Scoping. (1)


Verweise:

  1. diese & Objektprototypen, von Kyle Simpson. 2014 Gettify-Lösungen.
  2. javascriptsexy.com - http://goo.gl/pvl0GX 
  3. Angus Croll - http://goo.gl/Z2RacU 

12
2018-06-27 13:15



Jeden Funktion  Ausführungskontext in Javascript hat eine Umfang  Kontext  Dies Parameter, der eingestellt wird durch:

  1. Wie die Funktion aufgerufen wird (einschließlich als Objektmethode, Verwendung von Anruf und sich bewerben, Gebrauch von Neu)
  2. Gebrauch von binden
  3. Lexikalisch für Pfeilfunktionen (sie übernehmen die Dies ihres äußeren Ausführungskontextes)

Was auch immer dieser Kontextkontext ist, wird von "this" referenziert.

Sie können ändere das setze den Wert von Dies  Umfang  Kontext verwenden func.call, func.apply oder func.bind.

Standardmäßig, und was verwirrt die meisten Anfänger, wenn a Rückrufen listener wird aufgerufen, nachdem ein Ereignis für ein DOM - Element ausgelöst wurde Bereich Kontext  Dies Wert der Funktion ist das DOM-Element.

jQuery macht dieses Trivial mit jQuery.proxy zu ändern.


9
2017-11-29 06:01



Hier ist eine gute Quelle für this im JavaScript.

Hier ist die Zusammenfassung:

  • global dies

    In einem Browser, im globalen Umfang, this ist der windowObjekt

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

    Im node mit dem repl, this ist der oberste Namensraum. Sie können sich darauf beziehen als global.

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

    Im node Ausführen von einem Skript, this im globalen Bereich beginnt als leeres Objekt. Es ist nicht das Gleiche wie global

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

Außer im Fall von DOM Event Handlern oder wenn a thisArg bereitgestellt wird (siehe weiter unten), sowohl im Knoten als auch in einem Browser mit thisin einer Funktion, die nicht mit aufgerufen wird new verweist auf den globalen Geltungsbereich ...

<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 du benutzt use strict;, in welchem ​​Fall this wird sein undefined

<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 mit aufrufen new das this Es wird ein neuer Kontext sein, es wird nicht auf das Globale Bezug nehmen 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

Funktionen, die Sie erstellen, werden zu Funktionsobjekten. Sie bekommen automatisch ein besonderes prototype Eigenschaft, der Sie Werte zuweisen können. Wenn Sie eine Instanz erstellen, indem Sie Ihre Funktion mit aufrufen new Sie erhalten Zugriff auf die Werte, die Sie dem prototype Eigentum. Sie greifen auf diese Werte mit 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, zuzuweisen Arrays oder Objekte auf der prototype. Wenn Instanzen eigene Arrays haben sollen, erstellen Sie sie in der Funktion, 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 []
  • wende dies an

Sie können verwenden this in einer beliebigen Funktion eines Objekts, um auf andere Eigenschaften dieses Objekts zu 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-Ereignis dies

In einem HTML-DOM-Ereignishandler this ist immer ein Verweis auf das DOM-Element, 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();

Außer du bind der 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

Innerhalb von HTML-Attributen, in die Sie JavaScript einfügen können, this ist eine Referenz auf das Element.

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

Sie können verwenden eval zugreifen 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 verwenden with hinzufügen this in den aktuellen Bereich zum Lesen und Schreiben von Werten auf this ohne Bezug zu nehmen this ausdrücklich.

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 dies

Die jQuery wird an vielen Stellen haben this beziehen sich auf ein DOM-Element.

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

7
2018-04-23 12:57