
De acordo com algumas pesquisas , as funções de seta anônima no JavaScript são o recurso mais popular do ES-2015, o que também é destacado pelo amplo número de tutoriais na Internet. Eles são inegavelmente muito úteis, mas neste breve artigo veremos exemplos de como usar a atenção privada, pelo menos, expressões maravilhosas com funções nomeadas - NFE.
Ajuda curta
Expressão de função nomeada - uma extensão de expressões funcionais em JavaScript que permite nomear uma função criada como parte de uma expressão ( FunctionExpression ):
let fe = function named(...) { };
O ponto principal é que, dentro da função referenciada pela variável fe , há acesso à própria função através do nome nomeado . É impossível reescrever o nome apenas de dentro da função!
Como usá-lo
Por exemplo, precisamos escrever uma função de decoração que conte o número de chamadas para alguma função. Isso pode ser feito de maneira bastante elegante com a NFE:
const count = f => function df() { df.calls = (df.calls || 0) + 1; return f(...arguments); };
Aqui temos acesso à função df retornada, para que, quando for chamada, salve o contador na propriedade calls , que estará disponível para leitura, se necessário:
const csum = count((x, y) => x + y); csum(5, 10);
Ou salve todos os resultados da chamada de função:
const accum = f => function df() { let res = f(...arguments); (df.results = (df.results || [])).push(res); return res; };
De qualquer forma, aproveitamos o fato de que uma função em JavaScript é um objeto e podemos complementá-la com as propriedades necessárias em nossas tarefas locais.
Obviamente, podemos chamar uma função. Usar a NFE para recursão é especialmente bom. Suponha que desejamos encontrar o enésimo membro da sequência de Fibonacci (por algum motivo, todo mundo quer isso mais cedo ou mais tarde):
const rf = function getfn(n) { return n > 2 ? getfn(n - 2) + getfn(n - 1) : 1; }; rf(1);
Não vale a pena prestar atenção ao "tailing" aqui. Mas na capacidade de fazer o mesmo através da FunctionDeclaration - sim. Mas a função de expressão tem uma vantagem: se você deseja transferir a função de rf para outra variável, não precisa editar a chamada recursiva interna.
Um exemplo puro de uma implementação de timer:
const ping = (callback, t) => setTimeout(function pf() { callback(); setTimeout(pf, t); }, t);
Aqui usamos NFE como literal como argumento, em vez de declarar uma variável desnecessária. Por que não setInterval ? Em vez de um retorno de chamada, aqui pode haver uma espera por uma resolução da promessa antes do próximo tique do cronômetro.
Um exemplo interessante seria a combinação de NFE e IIFE ( Expressão de Função Imediatamente Invocada ), quando em vigor apenas o resultado da função recursiva é necessário. Apenas uma vez:
let data = { f10: function fact(n) { return n > 1 ? n * fact(n - 1) : 1; }(10) }; data.f10;
É isso mesmo? bem, aqui está o verdadeiro problema: existe alguma função estritamente crescente f que atua no conjunto de números naturais. Encontre o ponto extremo x no qual o valor da função não excede o y fornecido. Um exemplo dessa função seria f(x) = 3 * x + 5
ou f(x) = 2^x + 11
.
const find = (f, y) => function bs(a, b) { if (a + 1 === b) return a; let m = Math.ceil((a + b) / 2); return f(m) <= y ? bs(m, b) : bs(a, m); }(-1, y + 1); find(x => 3 * x + 5, 200);
Não entraremos em detalhes matemáticos. Considere a implementação:
- A função de busca necessária possui dois de nossos parâmetros f, y e retorna o resultado de IIFE.
- Uma função chamada instantaneamente implementa uma pesquisa binária por uma solução; a primeira chamada obtém o intervalo inicial.
- A pesquisa em si é implementada por meio de recursão, que usa o nome NFE para chamadas subseqüentes. Não declaramos uma função de pesquisa e não criamos uma nova variável.
Obviamente, um problema semelhante pode ser resolvido por meio de um ciclo simples com uma pré-condição, mas isso é imperativo demais para a codificação do console.
Finalmente, algumas palavras sobre o rastreamento de pilha. Temos alguma função NFE, no corpo da qual uma exceção foi lançada:
const fe = function named() { throw new Error('Something went wrong'); };
Como temos uma função nomeada na expressão, a veremos no rastreamento da pilha:
Uncaught Error: Something went wrong at named (<anonymous>:2:11)
No entanto, a partir do ES-2015, muitas expressões de função anônimas realmente criam uma função com um nome, tirando-a do contexto:
const unnamed = function() { throw new Error('Something went wrong'); };
A função no lado direito da expressão está associada à variável à esquerda:
Uncaught Error: Something went wrong at unnamed (<anonymous>:2:7)
Mas isso nem sempre é possível. Um exemplo clássico é a inicialização de um script de biblioteca externa através do IIFE, como uma opção:
;(function() {
Ou um exemplo frequente de uma função retornando outra função:
const bind = (f, ctx) => function() { return f.apply(ctx, arguments); };
Não há variável para saída, portanto, no caso de uma exceção, veremos o anônimo . A NFE pode ajudar um pouco em litígios.
Breve conclusão
A NFE é boa em escrever códigos concisos e sem suporte para prototipar rapidamente uma ampla variedade de tarefas. Para usar sua beleza no código final, pense duas vezes: o JavaScript já está sobrecarregado com especificações interessantes.