Bonjour, Habr! Je vous présente la traduction de l'article
«Que faire quand« cela »perd le contexte» de
Cristi Salcescu .
La meilleure façon d'éviter de perdre
ce contexte est de ne pas l'utiliser. Mais ce n'est pas toujours possible. Par exemple, nous travaillons avec le code ou la bibliothèque d'une autre personne qui l'utilise.
Littéral d'objet, fonction constructeur, constructeur d'objet de classe dans le système prototype. Ce pseudo-
paramètre est utilisé dans le système de prototypage afin de donner accès aux propriétés de l'objet.
Regardons quelques cas.
Fonctions imbriquées
cela perd la référence de contexte à l'intérieur des fonctions imbriquées.
class Service { constructor(){ this.numbers = [1,2,3]; this.token = "token"; } doSomething(){ setTimeout(function doAnotherThing(){ this.numbers.forEach(function log(number){
La méthode
doSomething () a deux fonctions imbriquées:
doAnotherthing () et
log () . Lorsque vous appelez
service.doSomething () ,
cela perd la référence de contexte dans la fonction imbriquée.
bind ()
Une façon de résoudre le problème est d'
utiliser la méthode
bind () . Jetez un œil au code suivant:
doSomething(){ setTimeout(function doAnotherThing(){ this.numbers.forEach(function log(number){ console.log(number); console.log(this.token); }.bind(this)); }.bind(this), 100); }
bind () crée une nouvelle version de la fonction qui, lorsqu'elle est appelée, a déjà une certaine valeur.
La fonction doAnotherThing () {/*...*/}.bind(this) crée une version de la fonction
doAnotherThing () , qui prend la valeur de
ceci de
doSomething () .
ça / moi
Une autre option consiste à déclarer et à utiliser la nouvelle variable
that / self , qui stockera la valeur
this de la méthode
doSomething () .
doSomething(){ let that = this; setTimeout(function doAnotherThing(){ that.numbers.forEach(function log(number){ console.log(number); console.log(that.token); }); }, 100); }
Nous devons déclarer
let that = this dans toutes les méthodes utilisant
this dans des fonctions imbriquées.
Fonctions fléchées
La fonction flèche nous donne une autre façon de résoudre ce problème.
doSomething(){ setTimeout(() => { this.numbers.forEach(number => { console.log(number); console.log(this.token); }); }, 100); }
Les fonctions fléchées ne créent pas leur propre contexte pour
cela , mais utilisent plutôt la valeur
this du contexte environnant. Dans l'exemple ci-dessus, il utilise la valeur de
this de la fonction parent.
L'inconvénient de cette méthode est que nous ne pouvons pas spécifier le nom de la fonction flèche. Le nom de la fonction joue un rôle important, car il augmente la lisibilité du code et décrit son objectif.
Voici le même code avec une fonction exprimée en termes de nom de variable:
doSomething(){ let log = number => { console.log(number); console.log(this.token); } let doAnotherThing = () => { this.numbers.forEach(log); } setTimeout(doAnotherThing, 100); }
Fonctions de rappel (méthode comme rappel)
cela perd la référence de contexte lors de l'utilisation de la méthode comme fonction de rappel. Regardons la classe suivante:
class Service { constructor(){ this.token = "token"; } doSomething(){ console.log(this.token);
Examinons les situations dans lesquelles la méthode
service.doSomething () est utilisée comme fonction de rappel.
Dans tous les cas ci-dessus,
cela perd le lien de contexte.
bind ()
Nous pouvons utiliser
bind () pour résoudre ce problème. Voici le code de cette option:
Fonction flèche
Une autre façon consiste à créer une fonction de flèche qui appelle
service.doSomething () .
Composants React
Dans les composants,
cela perd la référence de contexte lorsque les méthodes sont utilisées comme rappels pour les événements.
class TodoAddForm extends React.Component { constructor(){ super(); this.todos = []; } componentWillMount() { this.setState({desc: ""}); } add(){ let todo = {desc: this.state.desc};
Comme solution, nous pouvons créer de nouvelles fonctions dans le constructeur qui utiliseront
bind (this) .
constructor(){ super(); this.todos = []; this.handleChange = this.handleChange.bind(this); this.add = this.add.bind(this); }
N'utilisez pas «this»
Non, pas de problème de perte de contexte. Les objets peuvent être créés à l'aide
des fonctions d'usine . Jetez un œil à cet exemple:
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 }); }
Le contexte reste si vous utilisez la méthode comme rappel.
let service = Service(); service.doSomething();
Conclusion
cela perd la référence de contexte dans diverses situations.
bind () , en utilisant
cette variable
/ self et les fonctions flèches sont des moyens de résoudre les problèmes de contexte.
Les fonctions d'usine permettent de créer des objets sans l'utiliser.