As novas funções de seta es6 dizem return
estar implícitas em algumas circunstâncias:
A expressão também é o valor de retorno implícito dessa função.
Em quais casos eu preciso usar return
com as funções de seta es6?
As novas funções de seta es6 dizem return
estar implícitas em algumas circunstâncias:
A expressão também é o valor de retorno implícito dessa função.
Em quais casos eu preciso usar return
com as funções de seta es6?
Respostas:
Jackson respondeu parcialmente a isso em uma pergunta semelhante:
Retorno implícito, mas apenas se não houver bloqueio.
- Isso resultará em erros quando um one-liner se expandir para várias linhas e o programador esquecer de adicionar um
return
.- O retorno implícito é sintaticamente ambíguo.
(name) => {id: name}
retorna o objeto{id: name}
... certo? Errado. Retornaundefined
. Essas chaves são um bloco explícito.id:
é um rótulo.
Eu acrescentaria a isso a definição de um bloco :
Uma instrução de bloco (ou instrução composta em outros idiomas) é usada para agrupar zero ou mais instruções. O bloco é delimitado por um par de colchetes.
Exemplos :
// 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')
name
com a função entre parênteses e invocada com um argumento, "Jess". O código entre =>
e )('Jess')
em cada caso é o corpo da função de seta. Considere-o como uma forma abreviada de uma Expressão de Função Imediatamente Invocada do formulário(function (name) { return { id: name } })('Jess')
{}
) ou um bloco , ele assume que a { }
denota um bloco. Isso significa que, quando vê id: name
, acha que id:
é uma expressão que cria um rótulo (um recurso muito incomum do JS que lida com controle de fluxo e usa a :
) e, a name
seguir, id:
é simplesmente uma declaração separada que contém apenas a variável name
(& faz nada).
Eu entendo essa regra de ouro ...
Para funções que são efetivamente transformadas (manipulação de argumentos de uma linha), o retorno é implícito.
Os candidatos são:
// square-root
value => Math.sqrt(value)
// sum
(a,b) => a+b
Para outras operações (mais de uma linha que requerem um bloco, o retorno deve ser explícito
Há outro caso aqui.
Ao gravar um componente funcional no React, é possível usar parênteses para agrupar JSX retornado implicitamente.
const FunctionalComponent = () => (
<div>
<OtherComponent />
</div>
);
As funções de seta permitem um retorno implícito: os valores são retornados sem a necessidade de usar a return
palavra - chave.
Funciona quando há uma instrução on-line no corpo da função:
const myFunction = () => 'test'
console.log(myFunction()) //'test'
Outro exemplo, retornando um objeto (lembre-se de colocar os colchetes entre parênteses para evitar que sejam considerados os colchetes da função de empacotamento):
const myFunction = () => ({value: 'test'})
console.log(myFunction()) //{value: 'test'}
Aqui está outro caso que me deu alguns problemas.
// the "tricky" way
const wrap = (foo) => (bar) => {
if (foo === 'foo') return foo + ' ' + bar;
return 'nofoo ' + bar;
}
Aqui, definimos uma função que retorna uma função anônima. O bit "complicado" é que o corpo da função externa (a parte que começa com (bar) => ...) visualmente se parece com um "bloco", mas não é. Como não é, o retorno implícito entra em ação.
Aqui está como o wrap seria executado:
// 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'));
A maneira como eu descompactei isso para garantir que eu entendesse era "desfazer a estreitamento" das funções.
Aqui está o equivalente semântico do primeiro bloco de código, simplesmente fazendo o corpo de wrap () fazer um retorno explícito. Esta definição produz os mesmos resultados que acima. É aqui que os pontos se conectam. Compare o primeiro bloco de código acima com o bloco abaixo e fica claro que uma função de seta é tratada como uma expressão, não como um bloco, e tem o retorno implícito .
// the explicit return way
const wrap = (foo) => {
return (bar) => {
if (foo === 'foo') return foo + ' ' + bar;
return 'nofoo ' + bar;
}
}
A versão totalmente não-restrita do wrap seria assim, que apesar de não ser tão compacta quanto a versão com flecha, parece muito mais fácil de entender.
// the "no arrow functions" way
const wrap = function(foo) {
return function(bar) {
if (foo === 'foo') return foo + ' ' + bar;
return 'nofoo ' + bar;
};
};
No final, para outros que talvez precisem ler meu código e me futuro, acho que prefiro usar a versão sem flechas que pode ser compreendida visualmente à primeira vista, em vez da flecha que exige bastante pensei (e no meu caso experimentação) a grok.