¿Cuándo debo usar `return` en es6 Funciones de flecha?

Respuestas:

262

Jackson ha respondido parcialmente esto en una pregunta similar:

Retorno implícito, pero solo si no hay bloque.

  • Esto dará lugar a errores cuando una línea se expande a varias líneas y el programador olvida agregar un return.
  • El retorno implícito es sintácticamente ambiguo. (name) => {id: name}devuelve el objeto {id: name}... ¿verdad? Incorrecto. Vuelve undefined. Esas llaves son un bloque explícito. id:Es una etiqueta.

Agregaría a esto la definición de un bloque :

Una declaración de bloque (o declaración compuesta en otros idiomas) se usa para agrupar cero o más declaraciones. El bloque está delimitado por un par de llaves.

Ejemplos :

// 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
fuente
No entiendo esa sintaxis ... ¿estás creando una clase usando un litoral de clase y luego llamando a un constructor implícito con un argumento ('Jess')? Pensé que lo harías con esto ((nombre) => ({id: 'Jess'}))
Michael Dausmann
3
@MichaelDausmann Es una función de flecha que tiene un parámetro, namecon la función entre paréntesis e invocada con un argumento, "Jess". El código entre =>y )('Jess')en cada caso es el cuerpo de la función de flecha. Considérelo como una forma corta de una expresión de función invocada inmediatamente de la forma(function (name) { return { id: name } })('Jess')
Russ Cam
Muy útil indded! ayuda a detectar problemas en Promises.todos esos mapas sobre elementos con una función de flecha y puede notar si obtiene una matriz de indefinido si no se devuelve ningún valor para la asignación sobre matriz con funciones de flecha.
Jay Shah
¿Cuál habría sido la desventaja de hacer que el retorno implícito sea sistemático para las funciones de flecha? Al igual que coffeescript hace ... (aunque no me gusta coffeescript)
Augustin Riedinger
44
Para ser claros, parece que debido a que el analizador JS no sabe si esperar una expresión (como una expresión que contiene un objeto literal {}) o un bloque , supone que a { }denota un bloque. Eso significa que cuando ve id: name, piensa que id:es una expresión que crea una etiqueta (una característica muy poco común de JS que se ocupa del control de flujo y usa a :), y luego lo namesiguiente id:es simplemente una declaración separada que solo contiene la variable name(& no hace nada).
iono
18

Entiendo esta regla de oro ...

Para las funciones que son transformaciones efectivas (manipulaciones de argumentos en una línea), el retorno es implícito.

Los candidatos son:

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

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

Para otras operaciones (más de una línea que requieren un bloque, el retorno debe ser explícito

Amarsh
fuente
11

Hay otro caso aquí.

Al escribir un componente funcional en React, puede usar paréntesis para ajustar JSX devuelto implícitamente.

const FunctionalComponent = () => (
  <div>
    <OtherComponent />
  </div>
);
Deci
fuente
44
Siempre puedes usar paréntesis, no está relacionado con JSX o React.
Emile Bergeron
4

Aquí hay otro caso que me dio algunos problemas.

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

Aquí definimos una función que devuelve una función anónima. El bit "complicado" es que el cuerpo de la función para la función externa (la parte que comienza con (bar) => ...) se ve visualmente como un "bloque", pero no lo es. Como no es así, el retorno implícito entra en juego.

Así es como se ejecutaría wrap:

// 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 forma en que desempaqué esto para asegurarme de que entendí que era "desarreglar" las funciones.

Aquí está el equivalente semántico del primer bloque de código, simplemente haciendo que el cuerpo de wrap () haga un retorno explícito. Esta definición produce los mismos resultados que arriba. Aquí es donde se conectan los puntos. Compare el primer bloque de código anterior con el siguiente, y está claro que una función de flecha en sí misma se trata como una expresión, no como un bloque, y tiene el retorno implícito .

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

La versión totalmente desarmado de wrap sería así, que aunque no es tan compacta como la versión con flechas gruesas, parece mucho más fácil de comprender.

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

Al final, para otros que tengan que leer mi código, y para el futuro, creo que preferiría ir a la versión sin flecha que se puede comprender visualmente a primera vista, en lugar de la flecha que requiere un poco de tiempo. Pensé (y en mi caso experimentación) a grok.

Grayjohn
fuente
3

Las funciones de flecha le permiten tener un retorno implícito: los valores se devuelven sin tener que usar la returnpalabra clave.

Funciona cuando hay una declaración en línea en el cuerpo de la función:

const myFunction = () => 'test'

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

Otro ejemplo, devolver un objeto (recuerde colocar los corchetes entre paréntesis para evitar que se considere los corchetes de la función de ajuste):

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

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

Flavio Copes
fuente
1
Esta debería ser la respuesta correcta, aunque necesita un poco más de explicación. Básicamente, cuando el cuerpo de la función es una expresión, no un bloque, el valor de esa expresión se devuelve implícitamente. Corrígeme si me equivoco.
Paul-Sebastian Manole