Hallo Habr! Ich präsentiere Ihnen die Übersetzung des Artikels
„Was tun, wenn„ dies “den Kontext verliert ? “ Von
Cristi Salcescu .
Der beste Weg, um zu vermeiden, dass
dieser Kontext verloren geht, besteht darin, ihn nicht zu verwenden. Dies ist jedoch nicht immer möglich. Zum Beispiel arbeiten wir mit dem Code oder der Bibliothek einer anderen Person, die
dies verwendet .
Objektliteral, Konstruktorfunktion, Klassenobjektkonstruktor im Prototypsystem. Dieser Pseudoparameter
wird im Prototyping-System verwendet, um Zugriff auf die Eigenschaften des Objekts zu erhalten.
Schauen wir uns einige Fälle an.
Verschachtelte Funktionen
Dadurch geht die Kontextreferenz in verschachtelten Funktionen verloren.
class Service { constructor(){ this.numbers = [1,2,3]; this.token = "token"; } doSomething(){ setTimeout(function doAnotherThing(){ this.numbers.forEach(function log(number){
Die Methode
doSomething () verfügt über zwei verschachtelte Funktionen:
doAnotherthing () und
log () . Beim Aufruf von
service.doSomething () geht die Kontextreferenz in der verschachtelten Funktion verloren.
bind ()
Eine Möglichkeit, das Problem zu lösen, ist die
bind () -Methode. Sehen Sie sich den folgenden Code an:
doSomething(){ setTimeout(function doAnotherThing(){ this.numbers.forEach(function log(number){ console.log(number); console.log(this.token); }.bind(this)); }.bind(this), 100); }
bind () erstellt eine neue Version der Funktion, die beim Aufruf bereits einen bestimmten Wert
davon hat .
Die Funktion doAnotherThing () {/*...*/}.bind(this) erstellt eine Version der Funktion
doAnotherThing () , die den Wert von
doSomething () übernimmt.
das / selbst
Eine andere Möglichkeit besteht darin, die neue Variable
that / self zu deklarieren und zu verwenden, in der
dieser Wert aus der Methode
doSomething () gespeichert wird.
doSomething(){ let that = this; setTimeout(function doAnotherThing(){ that.numbers.forEach(function log(number){ console.log(number); console.log(that.token); }); }, 100); }
Wir müssen
let that = this in allen Methoden deklarieren
, die dies in verschachtelten Funktionen verwenden.
Pfeilfunktionen
Die Pfeilfunktion gibt uns eine andere Möglichkeit, dieses Problem zu lösen.
doSomething(){ setTimeout(() => { this.numbers.forEach(number => { console.log(number); console.log(this.token); }); }, 100); }
Pfeilfunktionen erstellen hierfür keinen eigenen Kontext, sondern verwenden
diesen Wert des umgebenden Kontexts. Im obigen Beispiel wird der Wert
dieser Funktion
der übergeordneten Funktion verwendet.
Der Nachteil dieser Methode ist, dass wir den Namen der Pfeilfunktion nicht angeben können. Der Name der Funktion spielt eine wichtige Rolle, da er die Lesbarkeit des Codes erhöht und seinen Zweck beschreibt.
Unten finden Sie denselben Code mit einer Funktion, die in Form eines Variablennamens ausgedrückt wird:
doSomething(){ let log = number => { console.log(number); console.log(this.token); } let doAnotherThing = () => { this.numbers.forEach(log); } setTimeout(doAnotherThing, 100); }
Rückruffunktionen (Methode als Rückruf)
Dies verliert die Kontextreferenz, wenn die Methode als Rückruffunktion verwendet wird. Schauen wir uns die folgende Klasse an:
class Service { constructor(){ this.token = "token"; } doSomething(){ console.log(this.token);
Schauen wir uns Situationen an, in denen die Methode
service.doSomething () als Rückruffunktion verwendet wird.
In allen oben genannten Fällen verliert dies die Kontextverknüpfung.
bind ()
Wir können
bind () verwenden , um dieses Problem zu lösen. Unten ist der Code für diese Option:
Pfeilfunktion
Eine andere Möglichkeit besteht darin, eine Pfeilfunktion zu erstellen, die
service.doSomething () aufruft.
Komponenten reagieren
In Komponenten verliert
dies die Kontextreferenz, wenn Methoden als Rückrufe für Ereignisse verwendet werden.
class TodoAddForm extends React.Component { constructor(){ super(); this.todos = []; } componentWillMount() { this.setState({desc: ""}); } add(){ let todo = {desc: this.state.desc};
Als Lösung können wir im Konstruktor neue Funktionen erstellen, die
bind (this) verwenden .
constructor(){ super(); this.todos = []; this.handleChange = this.handleChange.bind(this); this.add = this.add.bind(this); }
Verwenden Sie nicht "dies"
Nein
das - keine Probleme mit Kontextverlust. Objekte können mit
Factory-Funktionen erstellt werden. Schauen Sie sich dieses Beispiel an:
function Service() { let numbers = [1,2,3]; let token = "token"; function doSomething(){ setTimeout(function doAnotherThing(){ numbers.forEach(function log(number){ console.log(number); console.log(token); }); }, 100); } return Object.freeze({ doSomething }); }
Der Kontext bleibt erhalten, wenn Sie die Methode als Rückruf verwenden.
let service = Service(); service.doSomething();
Fazit
Dies verliert in verschiedenen Situationen den Kontextbezug.
bind () , die
diese / self- Variablen- und Pfeilfunktionen verwenden, sind Möglichkeiten, Kontextprobleme zu lösen.
Factory-Funktionen ermöglichen das Erstellen von Objekten ohne
diese .