Quando dovrei usare `return` in es6 Arrow Functions?


Risposte:


262

Jackson ha parzialmente risposto a questa domanda in una domanda simile:

Ritorno implicito, ma solo se non è presente alcun blocco.

  • Ciò comporterà errori quando una riga si espande su più righe e il programmatore dimentica di aggiungere un return.
  • Il ritorno implicito è sintatticamente ambiguo. (name) => {id: name}restituisce l'oggetto {id: name}... giusto? Sbagliato. Ritorna undefined. Quelle parentesi graffe sono un blocco esplicito. id:è un'etichetta.

Aggiungerei a questo la definizione di un blocco :

Un'istruzione di blocco (o un'istruzione composta in altre lingue) viene utilizzata per raggruppare zero o più istruzioni. Il blocco è delimitato da una coppia di parentesi graffe.

Esempi :

// 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') 

Non capisco quella sintassi .. stai creando una classe usando un littoral di classe e poi chiamando un costruttore implicito con un argomento ('Jess') ?? Ho pensato che avresti fatto questo ((name) => ({id: 'Jess'}))
Michael Dausmann,

3
@MichaelDausmann È una funzione freccia che ha un parametro, namecon la funzione racchiusa tra parentesi e invocata con un argomento, "Jess". Il codice tra =>e )('Jess')in ogni caso è il corpo della funzione freccia. Consideralo come una breve forma di un'espressione di funzione immediatamente invocata del modulo(function (name) { return { id: name } })('Jess')
Russ Cam

Indded molto utile! aiuta a individuare i problemi in Promises.all che mappano gli elementi con una funzione freccia e si può notare se si ottiene un array di indefinito se non è stato restituito alcun valore per il mapping su array con funzioni freccia.
Jay Shah,

Quale sarebbe stato il rovescio della medaglia nel rendere sistematico il ritorno implicito per le funzioni freccia? Proprio come fa coffeescript ... (anche se non mi piace il coffeescript)
Augustin Riedinger,

4
Per essere chiari, sembra che, poiché il parser JS non sa se aspettarsi un'espressione (come un'espressione contenente un oggetto letterale {}) o un blocco , assume che un { }denoti un blocco. Ciò significa che quando vede id: name, pensa che id:sia un'espressione che crea un'etichetta (una funzione molto insolita di JS che si occupa del controllo del flusso e usa a :), e quindi la nameseguente id:è semplicemente un'istruzione separata che contiene solo la variabile name(& non fa nulla).
iono,

18

Capisco questa regola empirica ...

Per le funzioni che sono effettivamente trasformate (manipolazioni di una riga di argomenti), il ritorno è implicito.

I candidati sono:

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

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

Per altre operazioni (più di una riga che richiedono un blocco, il ritorno deve essere esplicito


11

C'è un altro caso qui.

Quando si scrive un componente funzionale in React, è possibile utilizzare le parentesi per avvolgere JSX implicitamente restituito.

const FunctionalComponent = () => (
  <div>
    <OtherComponent />
  </div>
);

4
Puoi sempre usare le parentesi, non è correlato a JSX o React.
Emile Bergeron,

4

Ecco un altro caso che mi ha dato qualche problema.

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

Qui definiamo una funzione che restituisce una funzione anonima. Il bit "difficile" è che il corpo della funzione per la funzione esterna (la parte che inizia con (bar) => ...) appare visivamente come un "blocco", ma non lo è. Dato che non lo è, entra in gioco il ritorno implicito.

Ecco come eseguire il wrapping:

// 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'));

Il modo in cui l'ho decompresso per essere sicuro di aver capito che era di "unificare" le funzioni.

Ecco l'equivalente semantico del primo blocco di codice, facendo semplicemente in modo che il corpo di wrap () faccia un ritorno esplicito. Questa definizione produce gli stessi risultati di cui sopra. Questo è dove i punti si collegano. Confronta il primo blocco di codice sopra con quello sotto, ed è chiaro che una funzione freccia stessa viene trattata come un'espressione, non un blocco, e ha il ritorno implicito .

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

La versione completamente non ristretta di avvolgimento sarebbe così, che sebbene non sia compatta come la versione grassa con le frecce, sembra molto più facile da capire.

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

Alla fine, per gli altri che potrebbero dover leggere il mio codice, e futuro me, penso che preferirei andare alla versione non freccia che può essere compresa visivamente a prima vista, piuttosto che quella freccia che prende un bel po 'di ho pensato (e nel mio caso sperimentazione) a grok.


3

Le funzioni freccia consentono di ottenere un ritorno implicito: i valori vengono restituiti senza dover utilizzare la returnparola chiave.

Funziona quando è presente un'istruzione online nel corpo della funzione:

const myFunction = () => 'test'

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

Un altro esempio, restituendo un oggetto (ricordarsi di avvolgere le parentesi graffe tra parentesi per evitare che venga considerato le parentesi del corpo della funzione di avvolgimento):

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

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


1
Questa dovrebbe essere la risposta corretta, anche se necessita di qualche spiegazione in più. Fondamentalmente quando il corpo della funzione è un'espressione, non un blocco, il valore di quell'espressione viene restituito implicitamente. Correggimi se sbaglio.
Paul-Sebastian Manole,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.