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.
- Das Aufrufen der Funktion mit dem
newSchlüsselwort würde sofort einen ObjectTyp initialisieren Person.
- Für den Konstruktor
Objectist der Konstruktor festgelegt Person. Beachten Sie auch, dass typeof awalzurückkehren würde Objectnur.
- 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.
- 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:
- Was ist
thisstandardmäßig enthalten?
- Was ist, wenn wir die Funktion als Methode mit Objekt-Punkt-Notation aufrufen?
- Was ist, wenn wir die verwenden
new Schlüsselwort verwenden?
- Wie manipulieren wir
thismit callund apply?
- Verwenden von
bind.
- Kopieren,
thisum Probleme mit verschachtelten Bereichen zu lösen.