Contexte reliant lorsque vous appelez la méthode ES6. Comment accéder à l'objet à partir de la méthode appelée appel de rappel?

Je tente d'envelopper ma syntaxe pour Classes dans ES6. Tout en apprenant le tissu natif par l'intermédiaire de Bonnie Eisenman's Learning React Native.

Je suis confronté à un problème en ce qui concerne l'accès à this dans un rappel, lorsque ce rappel est une «méthode» de classe. Je suis conscient que les problèmes liés au lexical dans les rappels ont été soulevés à plusieurs reprises sur StackOverflow. Par exemple, dans Comment accéder au contexte correct `this` dans un rappel? .

Sur la base de mes recherches en ligne, j'ai rencontré une solution. Mais je ne suis pas sûr que ce soit la bonne façon de le faire dans ES6.

Mon problème s'est produit lorsque j'ai essayé ce qui suit ci-dessous:

 class WeatherProject extends Component { constructor(props) { super(props); this.state = { zip: '' }; } _handleTextChange(event) { console.log(event.nativeEvent.text); this.setState({zip: event.nativeEvent.text}) } render() { return ( <TextInput style={styles.input} onSubmitEditing={this._handleTextChange}/> ); } } 

(Ce que j'ai légèrement modifié de l'exemple dans le livre pour faire correspondre la syntaxe de classe ES6 et la syntaxe d'importation / exportation au lieu d'Exiger.)

Si je le fais, le this dans _handleTextChange est indéfini (impossible de lire la propriété 'setState' de indéfinie). J'ai été surpris par cela. En provenance d'autres langages OO, j'interprète comme si cette méthode se comportait davantage comme s'il s'agissait d'une méthode statique.

J'ai pu résoudre cela en ignorant la méthode de classe et en utilisant la notation de la flèche. onSubmitEditing={event => this.setState({name: event.nativeEvent.text})} . Ce qui fonctionne bien. Je n'ai aucun problème ni confusion avec cela.

Je souhaite vraiment savoir comment appeler une méthode de classe. Après un certain nombre de recherches, j'ai réussi à fonctionner en procédant comme suit: onSubmitEditing={this._handleTextChange.bind(this)} . Peut-être ai-je mal compris un aspect fondamental de JavaScript (je suis un débutant dans JS), mais cela me paraît complètement insensé. Est-il vraiment impossible d'accéder au contexte d'un objet à partir d'une méthode sans relier explicitement l'objet à … sa propre méthode, au point où elle s'appelle?

J'ai également essayé d'ajouter var self = this; Dans le constructeur et appeler self.setState dans _handleTextChange . Mais il n'était pas trop surpris de constater que cela ne marchait pas.

Quelle est la manière correcte d'accéder à un objet dans l'une de ses méthodes lorsqu'il est appelé comme rappel?

La forme de création de la forme React.createClass (ES5) comporte une fonctionnalité intégrée qui relie automatiquement toutes les méthodes à this méthode. Mais lors de l'introduction de classes dans ES6 et de la migration de React.createClass, ils ont trouvé que cela peut être un peu déroutant pour les développeurs JavaScript qui ne sont pas habitués à cette fonctionnalité dans d'autres classes, ou il peut être déroutant lorsqu'ils passent de React à d'autres classes.

Alors, ils ont décidé de ne pas l'intégrer dans le modèle de classe de React. Vous pouvez toujours pré-interdire explicitement les méthodes dans votre constructeur si vous voulez comme

 class WeatherProject extends Component { constructor(props) { super(props); this.state = { zip: '' }; this._handleTextChange = this._handleTextChange.bind(this); //Binding to `this` } _handleTextChange(event) { console.log(event.nativeEvent.text); this.setState({zip: event.nativeEvent.text}) } 

Mais nous avons toujours un moyen simple d'éviter ce pré-reliure. Ouais! Tu l'as eu. Fonctions de flèche.

 class WeatherProject extends Component { constructor(props) { super(props); this.state = { zip: '' }; } _handleTextChange = event => { console.log(event.nativeEvent.text); this.setState({zip: event.nativeEvent.text}) } render() { return ( <TextInput style={styles.input} onSubmitEditing={this._handleTextChange}/> ); } } 

BTW, Ceci concerne tout Réagir. La classe ES6 a toujours un moyen d'accéder au contexte d'un objet à partir d'une méthode sans relier explicitement l'objet à sa propre méthode.

 class bindTesting { constructor() { this.demo = 'Check 1'; } someMethod() { console.log(this.demo); } callMe() { this.someMethod(); } } let x = new bindTesting(); x.callMe(); //Prints 'Check 1'; 

Mais cela n'imprime pas «Vérifier 1» si nous l'appelons dans JSX Expression.

EDIT :: Comme mentionné par @Oka, les fonctions de flèche dans les corps de classe sont la fonctionnalité ES7 + et disponibles dans Compiler / polyfills comme babel. Si vous n'utilisez pas transpiler qui prend en charge cette fonctionnalité, nous pouvons simplement nous lier à this comme mentionné ci-dessus ou écrire un nouveau BaseComponent comme celui-ci (ce qui est une mauvaise idée)

 class BaseComponent extends React.Component { _bind(...methods) { methods.forEach( (method) => this[method] = this[method].bind(this) ); } } class ExampleComponent extends BaseComponent { constructor() { super(); this._bind('_handleTextChange', '_handleClick'); } // ... } 

En cas de rupture de ES6 et de réagir un moment, dans un ancien JavaScript ordinaire, lorsque vous passez la méthode d'un objet, il ne s'agit que d'une référence à la fonction elle-même, pas l'objet et la fonction.

Toute fonction d'appel peut choisir d'utiliser implicitement this , en appelant la fonction normalement, ou elle peut même choisir de modifier le contexte en utilisant .apply et .apply , ou .bind .

 var O = { foo: function () { console.log(this); }, bar: 51 }; O.foo(); // `this` is O, the implicit context, inferred from the object host var foo = O.foo; foo(); // `this` is is the global object, or undefined in Strict Mode 

Peut-être ai-je mal compris un aspect fondamental de JavaScript (je suis un débutant dans JS), mais cela me paraît complètement insensé. Est-il vraiment impossible d'accéder au contexte d'un objet à partir d'une méthode sans relier explicitement l'objet à … sa propre méthode, au point où elle s'appelle?

Eh bien, les «méthodes» ne sont pas la propriété d'objets en javascript. Toutes les fonctions sont des valeurs de première classe (objets), et non une "partie" d'un objet ou d'une classe.

La liaison de this valeur se produit lorsque la fonction est appelée, selon la façon dont la fonction est appelée. Un appel de fonction avec la notation de méthode est son ensemble pour l'objet récepteur, un appel d'écouteur d'événement a son ensemble sur la cible d'événement en cours, et un appel de fonction normale n'est undefined .

Si vous accédez à une méthode sur une instance, ce n'est vraiment que l'accès à la propriété de propriété de prototype standard qui produit une fonction, puis appelée et liée dynamiquement au destinataire.

Si vous souhaitez appeler une fonction en tant que méthode sur une instance lorsqu'il s'agit d'un auditeur d'événements, vous devez créer explicitement une fonction qui fait cela – la méthode "liée". Dans ES6, la notation de la flèche est généralement préférée pour cela.