Heim > Artikel > Web-Frontend > Mehrere Möglichkeiten, mit „diesem“ Zeiger in JS umzugehen
Ich ändere gerne den Zeiger des Funktionsausführungskontexts in JS, auch bekannt als this
-Zeiger.
Zum Beispiel können wir Array-Methoden für Array-ähnliche Objekte verwenden:
const reduce = Array.prototype.reduce; function sumArgs() { return reduce.call(arguments, (sum, value) => { return sum += value; }); } sumArgs(1, 2, 3); // => 6
Andererseits ist this
schwer zu verstehen.
Wir stellen oft fest, dass wir this
verwenden, um falsch zu zeigen. Im Folgenden erfahren Sie, wie Sie this
einfach an den gewünschten Wert binden.
Bevor ich anfange, benötige ich eine Hilfsfunktion execute(func)
, die lediglich die als Argument bereitgestellte Funktion ausführt.
function execute(func) { return func(); } execute(function() { return 10 }); // => 10
Jetzt kommen wir zum Verständnis der Natur des Fehlers im Zusammenhang mit this
: Methodentrennung.
1. Methodentrennungsproblem
Angenommen, es gibt eine Klasse Person
, die die Felder firstName
und lastName
enthält. Darüber hinaus gibt es eine Methode getFullName()
, die den vollständigen Namen der Person zurückgibt. Wie unten gezeigt:
function Person(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; this.getFullName = function() { this === agent; // => true return `${this.firstName} ${this.lastName}`; } } const agent = new Person('前端', '小智'); agent.getFullName(); // => '前端 小智'
Sie können sehen, dass die Funktion Person
als Konstruktor aufgerufen wird: new Person('前端', '小智')
. Das this
innerhalb der Funktion stellt die neu erstellte Instanz dar.
getfullname()
Gibt den vollständigen Namen der Person zurück: '前端 小智'
. Wie erwartet ist getFullName()
innerhalb der this
-Methode gleich agent
.
Was passiert, wenn die Hilfsfunktion die agent.getFullName
-Methode ausführt:
execute(agent.getFullName); // => 'undefined undefined'
Das Ausführungsergebnis ist falsch:'undefined undefined'
, was ein Problem ist, das durch falsches Zeigen von this
verursacht wird.
In der getFullName()
-Methode ist der Wert von this
nun das globale Objekt (window
im Browserkontext). this
ist gleich window
und das Ausführungsergebnis von ${window.firstName} ${window.lastName}
ist 'undefined undefined'
.
Dies geschieht, weil die Methode vom Objekt getrennt wird, wenn execute(agent.getFullName)
aufgerufen wird. Im Grunde handelt es sich lediglich um einen regulären Funktionsaufruf (keinen Methodenaufruf):
execute(agent.getFullName); // => 'undefined undefined' // 等价于: const getFullNameSeparated = agent.getFullName; execute(getFullNameSeparated); // => 'undefined undefined'
Das nennt man Trennen der Methode von ihrem Objekt. Wenn die Methode getrennt und dann ausgeführt wird, hat this
nichts damit zu tun mit dem ursprünglichen Objekt verbinden.
Um sicherzustellen, dass this
innerhalb der Methode auf das richtige Objekt zeigt, müssen Sie Folgendes tun:
Führen Sie die Methode als Eigenschaftszugriffsmethode aus: agent.getFullName()
this
statisch an das enthaltene Objekt (mithilfe von Pfeilfunktionen, .bind()
-Methoden usw.). Methodentrennungsproblem, und das resultierende this
-Zeigen ist im Allgemeinen falsch erscheint in den folgenden Situationen:
Rückruf
// `methodHandler()`中的`this`是全局对象 setTimeout(object.handlerMethod, 1000);
Beim Festlegen des Event-Handlers
// React: `methodHandler()`中的`this`是全局对象 <button onClick={object.handlerMethod}> Click me </button>
Dann stellen wir einige nützliche Methoden vor , nämlich wie man this
dazu bringt, auf das gewünschte Objekt zu zeigen, wenn die Methode vom Objekt getrennt ist.
2. Schließen Sie den Kontext
Der einfachste Weg, this
weiterhin auf die Klasseninstanz zu verweisen, ist die Verwendung einer zusätzlichen Variablen self
:
function Person(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; const self = this; this.getFullName = function() { self === agent; // => true return `${self.firstName} ${self.lastName}`; } } const agent = new Person('前端', '小智'); agent.getFullName(); // => '前端 小智' execute(agent.getFullName); // => '前端 小智'
getFullName()
schließt die Variable self
statisch und bindet this
effektiv manuell.
Wenn nun execute(agent.getFullName)
aufgerufen wird, funktioniert alles einwandfrei, da das getFullName()
in der this
-Methode immer auf den richtigen Wert zeigt.
3. Verwendung von Pfeilfunktionen
Gibt es eine Möglichkeit, this
ohne zusätzliche Variablen statisch zu binden? Ja, genau das machen Pfeilfunktionen.
RefactoringPerson
mit Pfeilfunktionen:
function Person(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; this.getFullName = () => `${this.firstName} ${this.lastName}`; } const agent = new Person('前端', '小智'); agent.getFullName(); // => '前端 小智' execute(agent.getFullName); // => '前端 小智'
Pfeilfunktionen sind lexikalisch an this
gebunden. Einfach ausgedrückt verwendet es den Wert der externen Funktion this
, in der er definiert ist.
Es wird empfohlen, Pfeilfunktionen in allen Fällen zu verwenden, in denen ein externer Funktionskontext erforderlich ist.
4. Bindungskontext
Gehen wir nun einen Schritt weiter und verwenden Klassen-Refactoring in ES6 Person
.
class Person { constructor(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; } getFullName() { return `${this.firstName} ${this.lastName}`; } } const agent = new Person('前端', '小智'); agent.getFullName(); // => '前端 小智' execute(agent.getFullName); // => 'undefined undefined'
Leider gibt execute(agent.getFullName)
trotz der neuen Klassensyntax immer noch “undefined undefined”
zurück.
Im Fall einer Klasse funktioniert die Verwendung einer zusätzlichen Variablen self
oder einer Pfeilfunktion zum Korrigieren der Ausrichtung von this
nicht.
Aber es gibt einen Trick mit einer bind()
-Methode, der den Kontext der Methode in den Konstruktor bindet:
class Person { constructor(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; this.getFullName = this.getFullName.bind(this); } getFullName() { return `${this.firstName} ${this.lastName}`; } } const agent = new Person('前端', '小智'); agent.getFullName(); // => '前端 小智' execute(agent.getFullName); // => '前端 小智'
this.getFullName = this.getFullName.bind(this)
im Konstruktor bindet die Methode getFullName()
an die Klasseninstanz .
execute(agent.getFullName)
funktioniert wie erwartet und gibt '前端 小智'
zurück.
5. Fettpfeil-Methode
bind
Die Methode ist etwas zu langwierig, wir können die Fettpfeil-Methode verwenden:
class Person { constructor(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; } getFullName = () => { return `${this.firstName} ${this.lastName}`; } } const agent = new Person('前端', '小智'); agent.getFullName(); // => '前端 小智' execute(agent.getFullName); // => '前端 小智'
胖箭头方法getFullName =() =>{…}
绑定到类实例,即使将方法与其对象分离。
这种方法是在类中绑定this
的最有效和最简洁的方法。
6. 总结
与对象分离的方法会产生 this 指向不正确问题。静态地绑定this
,可以手动使用一个附加变量self
来保存正确的上下文对象。然而,更好的替代方法是使用箭头函数,其本质上是为了在词法上绑定this
。
在类中,可以使用bind()
方法手动绑定构造函数中的类方法。当然如果你不用使用 bind
这种冗长方式,也可以使用简洁方便的胖箭头表示方法。
更多JavaScript知识请关注PHP中文网JavaScript视频教程栏目
Das obige ist der detaillierte Inhalt vonMehrere Möglichkeiten, mit „diesem“ Zeiger in JS umzugehen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!