Que signifie javascript pour plusieurs fonctions de flèche?

j'ai lu un tas de code react et je vois des trucs comme ça que je ne comprends pas:

handleChange = field => e => {
  e.preventDefault();
  /// Do something here
}
226
demandé sur Bergi 2015-09-25 16:06:31

4 réponses

Qui est une au curry fonction

tout d'abord, examiner cette fonction avec deux paramètres ...

let add = (x,y) => x + y;
add(2,3); //=> 5

la voici de nouveau en forme de curry ...

let add = x => y => x + y;

voici le même code 1 sans fonctions de flèche ...

let add = function (x) {
  return function (y) {
    return x + y;
  };
};

Focus sur return

cela pourrait aider à le visualiser d'une autre manière. Nous savons que les fonctions de flèche fonctionnent comme ceci – portons une attention particulière à la valeur de retour .

let f = someParam => returnValue

ainsi notre add renvoie une fonction – nous pouvons utiliser des parenthèses pour plus de clarté. Le en caractères gras texte est la valeur de retour de notre fonction add

let add = x => (y => x + y)

En d'autres termes add d'un nombre renvoie une fonction

add(2) // returns (y => 2 + y)

appelant les fonctions courantes

donc pour utiliser notre fonction curried, nous devons l'appeler un peu différemment ...

add(2)(3); // returns 5

c'est parce que le premier appel de fonction (externe) renvoie une seconde fonction (interne). Ce n'est qu'après avoir appelé la deuxième fonction que nous en fait obtenir le résultat. Cela est plus évident si nous séparons les appels sur deux lignes ...

let add2 = add(2); // returns function(y) { return 2 + y }
add2(3);           // returns 5

appliquer notre nouvelle compréhension à votre code

related: "Quelle est la différence entre la liaison, l'application partielle, et de nourrissage?"

OK, maintenant que nous comprenons comment cela fonctionne, regardons votre code

handleChange = field => e => {
  e.preventDefault();
  /// Do something here
}

nous allons commencer par le représenter sans utiliser les fonctions de flèche ...

handleChange = function(field) {
  return function(e) {
    e.preventDefault();
    // Do something here
    // return ...
  };
};

cependant, parce que les fonctions de la flèche lient lexicalement this , il serait en fait ressemblent plus à cela ...

handleChange = function(field) {
  return function(e) {
    e.preventDefault();
    // Do something here
    // return ...
  }.bind(this);
}.bind(this);

peut-être que maintenant nous pouvons voir ce que cela fait plus clairement. La fonction handleChange crée une fonction pour un field spécifié . C'est une technique de réaction pratique car vous devez configurer vos propres écouteurs sur chaque entrée afin de mettre à jour l'état de vos applications. En utilisant la fonction handleChange , nous pouvons éliminer tout le code dupliqué qui résulterait en mettant en place des écouteurs change pour chaque champ.

Cool !


1 ici, je n'ai pas eu à lier lexicalement this parce que l'original La fonction add n'utilise aucun contexte, il n'est donc pas important de la préserver dans ce cas.

371
répondu user633183 2018-08-25 00:01:05

comprendre les syntaxes disponibles des fonctions de flèche vous donnera une compréhension du comportement qu'ils introduisent quand "enchaîné" comme dans les exemples que vous avez fournis.

Lorsqu'une fonction de flèche est écrite sans attelles de bloc, avec ou sans paramètres multiples, l'expression qui constitue le corps de la fonction est implicitement retournée. Dans votre exemple, cette expression est une autre fonction de flèche.

No arrow funcs              Implicitly return `e=>{…}`    Explicitly return `e=>{…}` 
---------------------------------------------------------------------------------
function (field) {         |  field => e => {            |  field => {
  return function (e) {    |                             |    return e => {
      e.preventDefault()   |    e.preventDefault()       |      e.preventDefault()
  }                        |                             |    }
}                          |  }                          |  }

un autre avantage d'écrire des fonctions anonymes en utilisant la syntaxe des flèches est qu'elles sont liées lexicalement à la portée dans laquelle elles sont définies. De "Flèche fonctions de" MDN :

An arrow function expression a une syntaxe plus courte que function expressions et lie lexicalement la valeur this . Flèche les fonctions sont toujours anonyme .

ceci est particulièrement pertinent dans votre exemple étant donné qu'il est tiré d'une demande . Comme le souligne @naomik, dans React vous accédez souvent à un component's member functions en utilisant this . Par exemple:

Unbound                     Explicitly bound            Implicitly bound 
------------------------------------------------------------------------------
function (field) {         |  function (field) {       |  field => e => {
  return function (e) {    |    return function (e) {  |    
      this.setState(...)   |      this.setState(...)   |    this.setState(...)
  }                        |    }.bind(this)           |    
}                          |  }.bind(this)             |  }
43
répondu sdgluck 2017-04-07 15:35:48

pensez-y comme ceci, chaque fois que vous voyez une flèche, vous la remplacez par function .

function parameters sont définis avant la flèche.

Ainsi dans votre exemple:

field => // function(field){}
e => { e.preventDefault(); } // function(e){e.preventDefault();}

et puis ensemble:

function (field) { 
    return function (e) { 
        e.preventDefault(); 
    };
}

à Partir de la documentation :

// Basic syntax:
(param1, param2, paramN) => { statements }
(param1, param2, paramN) => expression
   // equivalent to:  => { return expression; }

// Parentheses are optional when there's only one argument:
singleParam => { statements }
singleParam => expression
24
répondu LifeQuery 2018-07-28 22:30:22

un conseil général , si vous êtes confus par une nouvelle syntaxe JS et comment elle se compilera , vous pouvez cocher babel . Par exemple, copier votre code dans babel et sélectionner le preset es2015 donnera une sortie comme celle-ci

handleChange = function handleChange(field) {
 return function (e) {
 e.preventDefault();
  // Do something here
   };
 };

babel

23
répondu Rahil Ahmad 2018-02-07 00:44:37