Quand dois-je utiliser `return` dans les fonctions fléchées es6?

Réponses:

262

Jackson a partiellement répondu à cela dans une question similaire:

Retour implicite, mais uniquement s'il n'y a pas de bloc.

  • Cela entraînera des erreurs lorsqu'une ligne unique se développe en plusieurs lignes et que le programmeur oublie d'ajouter un fichier return.
  • Le retour implicite est syntaxiquement ambigu. (name) => {id: name}renvoie l'objet {id: name}... non? Faux. Il revient undefined. Ces accolades sont un bloc explicite. id:est une étiquette.

J'ajouterais à cela la définition d'un bloc :

Une instruction de bloc (ou une instruction composée dans d'autres langues) est utilisée pour regrouper zéro ou plusieurs instructions. Le bloc est délimité par une paire de crochets.

Exemples :

// returns: undefined
// explanation: an empty block with an implicit return
((name) => {})() 

// returns: 'Hi Jess'
// explanation: no block means implicit return
((name) => 'Hi ' + name)('Jess')

// returns: undefined
// explanation: explicit return required inside block, but is missing.
((name) => {'Hi ' + name})('Jess')

// returns: 'Hi Jess'
// explanation: explicit return in block exists
((name) => {return 'Hi ' + name})('Jess') 

// returns: undefined
// explanation: a block containing a single label. No explicit return.
// more: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label
((name) => {id: name})('Jess') 

// returns: {id: 'Jess'}
// explanation: implicit return of expression ( ) which evaluates to an object
((name) => ({id: name}))('Jess') 

// returns: {id: 'Jess'}
// explanation: explicit return inside block returns object
((name) => {return {id: name}})('Jess') 
Jess Telford
la source
Je ne comprends pas cette syntaxe .. créez-vous une classe en utilisant une classe littoral et appelez-vous ensuite un constructeur implicite avec un argument ('Jess') ?? Je pensais que vous le feriez ((name) => ({id: 'Jess'}))
Michael Dausmann
3
@MichaelDausmann C'est une fonction fléchée qui a un paramètre,, nameavec la fonction entre parenthèses et appelée avec un argument, "Jess". Le code entre le =>et )('Jess')dans chaque cas est le corps de la fonction de flèche. Considérez-le comme une forme courte d'une expression de fonction immédiatement invoquée de la forme(function (name) { return { id: name } })('Jess')
Russ Cam
Très utile indiqué! aide à repérer les problèmes dans Promises.all qui mappent sur des éléments avec une fonction de flèche et vous pouvez remarquer si vous obtenez un tableau d'indéfini si aucune valeur n'a été renvoyée pour le mappage sur un tableau avec des fonctions de flèche.
jay shah
Quel aurait été l'inconvénient de rendre systématique le retour implicite pour les fonctions fléchées? Tout comme le fait coffeescript ... (même si je n'aime pas coffeescript)
Augustin Riedinger
4
Pour être clair, il semble que, comme l'analyseur JS ne sait pas s'il faut attendre une expression (telle qu'une expression contenant un objet littéral {}) ou un bloc , il suppose que a { }désigne un bloc. Cela signifie que lorsqu'il voit id: name, il pense que id:c'est une expression créant une étiquette (une fonctionnalité très peu utilisée de JS qui traite du contrôle de flux et utilise a :), puis ce qui namesuit id:est simplement une instruction séparée qui ne contient que la variable name(& ne fait rien).
iono
18

Je comprends cette règle de base ...

Pour les fonctions qui sont effectivement des transformations (manipulations d'arguments sur une ligne), le retour est implicite.

Les candidats sont:

// square-root 
value => Math.sqrt(value)

// sum
(a,b) => a+b

Pour les autres opérations (plus de one-liners qui nécessitent un bloc, le retour doit être explicite

Amarsh
la source
11

Il y a un autre cas ici.

Lors de l'écriture d'un composant fonctionnel dans React, vous pouvez utiliser des parenthèses pour encapsuler le JSX renvoyé implicitement.

const FunctionalComponent = () => (
  <div>
    <OtherComponent />
  </div>
);
Deci
la source
4
Vous pouvez toujours utiliser des parenthèses, cela n'a aucun rapport avec JSX ou React.
Emile Bergeron
4

Voici un autre cas qui m'a posé des problèmes.

// the "tricky" way
const wrap = (foo) => (bar) => {
  if (foo === 'foo') return foo + ' ' + bar;
  return 'nofoo ' + bar;
}

Ici, nous définissons une fonction retournant une fonction anonyme. Le point "délicat" est que le corps de la fonction externe (la partie commençant par (bar) => ...) ressemble visuellement à un "bloc", mais ce n'est pas le cas. Comme ce n'est pas le cas, le retour implicite entre en jeu.

Voici comment wrap s'exécuterait:

// use wrap() to create a function withfoo()
const withfoo = wrap('foo');
// returns: foo bar
console.log(withfoo('bar'));

// use wrap() to create a function withoutfoo()
const withoutfoo = wrap('bar');
// returns: nofoo bar
console.log(withoutfoo('bar'));

La façon dont j'ai déballé ceci pour m'assurer que je comprenais c'était de "désarrimer" les fonctions.

Voici l'équivalent sémantique du premier bloc de code, faisant simplement que le corps de wrap () fasse un retour explicite. Cette définition produit les mêmes résultats que ci-dessus. C'est là que les points se connectent. Comparez le premier bloc de code ci-dessus avec celui ci-dessous, et il est clair qu'une fonction de flèche elle-même est traitée comme une expression, pas un bloc, et a le retour implicite .

// the explicit return way
const wrap = (foo) => {
  return (bar) => {
    if (foo === 'foo') return foo + ' ' + bar;
    return 'nofoo ' + bar;
  }
}

La version entièrement non fléchée de wrap serait comme ça, qui, bien que pas aussi compacte que la version grosse flèche vers le haut, semble beaucoup plus facile à comprendre.

// the "no arrow functions" way
const wrap = function(foo) {
  return function(bar) {
    if (foo === 'foo') return foo + ' ' + bar;
    return 'nofoo ' + bar;
  };
};

En fin de compte, pour les autres qui devront peut-être lire mon code, et à l'avenir moi, je pense que je préférerais aller à la version sans flèche qui peut être comprise visuellement à première vue, plutôt que la version flèche qui prend un peu de pensé (et dans mon cas l'expérimentation) à grok.

Grayjohn
la source
3

Les fonctions fléchées vous permettent d'avoir un retour implicite: les valeurs sont renvoyées sans avoir à utiliser le returnmot - clé.

Cela fonctionne quand il y a une instruction en ligne dans le corps de la fonction:

const myFunction = () => 'test'

console.log(myFunction()) //'test'

Autre exemple, renvoyer un objet (n'oubliez pas de mettre les accolades entre parenthèses pour éviter qu'il ne soit considéré comme les crochets du corps de la fonction d'habillage):

const myFunction = () => ({value: 'test'})

console.log(myFunction()) //{value: 'test'}

Flavio Copes
la source
1
Cela devrait être la bonne réponse, même si elle nécessite un peu plus d'explications. Fondamentalement, lorsque le corps de la fonction est une expression, pas un bloc, la valeur de cette expression est renvoyée implicitement. Corrige moi si je me trompe.
Paul-Sebastian Manole