Heim  >  Artikel  >  Web-Frontend  >  Mehrere Möglichkeiten, mit „diesem“ Zeiger in JS umzugehen

Mehrere Möglichkeiten, mit „diesem“ Zeiger in JS umzugehen

尚
nach vorne
2020-06-18 17:18:031979Durchsuche

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:

  1. Führen Sie die Methode als Eigenschaftszugriffsmethode aus: agent.getFullName()

  2. Oder binden Sie 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(&#39;前端&#39;, &#39;小智&#39;);

agent.getFullName();        // => &#39;前端 小智&#39;
execute(agent.getFullName); // => &#39;前端 小智&#39;

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(&#39;前端&#39;, &#39;小智&#39;);

agent.getFullName();        // => &#39;前端 小智&#39;
execute(agent.getFullName); // => &#39;前端 小智&#39;

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); // => &#39;undefined undefined&#39;

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(&#39;前端&#39;, &#39;小智&#39;);

agent.getFullName();        // => &#39;前端 小智&#39;
execute(agent.getFullName); // => &#39;前端 小智&#39;

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(&#39;前端&#39;, &#39;小智&#39;);

agent.getFullName();        // => &#39;前端 小智&#39;
execute(agent.getFullName); // => &#39;前端 小智&#39;

胖箭头方法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!

Stellungnahme:
Dieser Artikel ist reproduziert unter:csdn.net. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen