Les nouvelles fonctions es6 arrow say return
sont implicites dans certaines circonstances:
L'expression est également la valeur de retour implicite de cette fonction.
Dans quels cas dois-je utiliser return
avec les fonctions fléchées es6?
Jackson a partiellement répondu à cette question dans une question similaire:
Retour implicite, mais uniquement s'il n'y a pas de blocage.
- Cela entraînera des erreurs lorsqu'un one-liner se développera sur plusieurs lignes et que le programmeur oubliera d'ajouter une
return
.- Le retour implicite est syntaxiquement ambigu.
(name) => {id: name}
retourne l'objet{id: name}
... non? Faux. Il retourneundefined
. 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 instruction ou plus. Le bloc est délimité par une paire d'accolades.
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')
Je comprends cette règle de base ...
Pour les fonctions effectivement transformées (manipulations d'arguments sur une ligne), return est implicite.
Les candidats sont:
// square-root
value => Math.sqrt(value)
// sum
(a,b) => a+b
Pour les autres opérations (plusieurs liners nécessitant un bloc, return doit être explicite
Il y a un autre cas ici.
Lors de l'écriture d'un composant fonctionnel dans React, vous pouvez utiliser des parenthèses pour envelopper le JSX renvoyé de manière implicite.
const FunctionalComponent = () => (
<div>
<OtherComponent />
</div>
);
Les fonctions fléchées vous permettent d'avoir un retour implicite: les valeurs sont renvoyées sans avoir à utiliser le mot clé return
.
Cela fonctionne quand il y a une déclaration en ligne dans le corps de la fonction:
const myFunction = () => 'test'
console.log(myFunction()) //'test'
Autre exemple, renvoyer un objet (n'oubliez pas de placer les accolades entre parenthèses pour éviter de le considérer comme étant les accolades du corps de la fonction d'emballage):
const myFunction = () => ({value: 'test'})
console.log(myFunction()) //{value: 'test'}
Voici un autre cas qui m'a causé quelques ennuis.
// the "tricky" way
const wrap = (foo) => (bar) => {
if (foo === 'foo') return foo + ' ' + bar;
return 'nofoo ' + bar;
}
Nous définissons ici une fonction renvoyant une fonction anonyme. Le bit "compliqué" signifie que le corps de la fonction pour 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écompressé cela pour m'assurer de bien comprendre était de "désaffiner" les fonctions.
Voici l'équivalent sémantique du premier bloc de code, faisant simplement que le corps de wrap () effectue 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 est elle-même 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;
}
}
Voici la version de wrap entièrement non affinée qui, bien qu’elle ne soit pas aussi compacte que la version grasse, 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 doivent lire mon code, et pour moi, je préférerais utiliser la version non flèche, qui peut être comprise à première vue, plutôt que celle qui prend beaucoup de temps. pensé (et dans mon cas, l'expérimentation) à grok.