Temos duas maneiras diferentes de fazer expressão de função em JavaScript:
Expressão de função nomeada (NFE) :
var boo = function boo () {
alert(1);
};
Expressão de função anônima :
var boo = function () {
alert(1);
};
E ambos podem ser chamados com boo();
. Eu realmente não consigo ver por que / quando devo usar funções anônimas e quando devo usar expressões de função nomeada. Que diferença existe entre eles?
javascript
function
anonymous-function
function-expression
Afshin Mehrabani
fonte
fonte
Respostas:
No caso da expressão de função anônima, a função é anônima - literalmente, não tem nome. A variável à qual você está atribuindo tem um nome, mas a função não. (Atualização: isso era verdade através do ES5. A partir do ES2015 [também conhecido como ES6], muitas vezes uma função criada com uma expressão anônima obtém um nome verdadeiro [mas não um identificador automático], continue lendo ...)
Os nomes são úteis. Os nomes podem ser vistos em rastreamentos de pilha, pilhas de chamadas, listas de pontos de interrupção, etc. Os nomes são uma coisa boa ™.
(Você costumava ter que tomar cuidado com as expressões de função nomeada em versões mais antigas do IE [IE8 e abaixo], porque eles criaram por engano dois objetos de função completamente separados em dois momentos completamente diferentes [mais no meu artigo do blog Double take ]. Se você precisar suporte IE8 [!!], provavelmente é melhor ficar com expressões de função anônimas ou declarações de função , mas evite expressões de função nomeadas.)
Uma coisa importante sobre uma expressão de função nomeada é que ela cria um identificador dentro do escopo com esse nome para a função dentro do corpo da função:
No entanto, a partir do ES2015, muitas expressões de função "anônimas" criaram funções com nomes, e isso foi precedido por vários mecanismos JavaScript modernos que eram bastante inteligentes ao inferir nomes a partir do contexto. No ES2015, sua expressão de função anônima resulta em uma função com o nome
boo
. No entanto, mesmo com a semântica ES2015 +, o identificador automático não é criado:A atribuição do nome da função é feita com a operação abstrata SetFunctionName usada em várias operações na especificação.
A versão curta é basicamente qualquer momento em que uma expressão de função anônima aparece no lado direito de algo como uma atribuição ou inicialização, como:
(ou pode ser
let
ou emconst
vez devar
) , ouou
(esses dois últimos são realmente a mesma coisa) , a função resultante terá um nome (
boo
, nos exemplos).Há uma exceção importante e intencional: atribuir a uma propriedade em um objeto existente:
Isso ocorreu devido a preocupações com vazamento de informações quando o novo recurso estava passando pelo processo de adição; detalhes em minha resposta a outra pergunta aqui .
fonte
new
operador (dar a todos esses nomes de funções torna a.constructor
propriedade mais útil durante a depuração para descobrir o que diabos algum objeto é uma instância de), e para literais de função passados diretamente para uma função sem primeiro serem atribuídos a uma propriedade ou variável (por exemplosetTimeout(function () {/*do stuff*/});
). Até mesmo o Chrome mostra esses(anonymous function)
nomes , a menos que você ajude nomeando-os.setTimeout
exemplo não pegasse o nome do argumento formal declarado parasetTimeout
, se houvesse um. :-) Mas sim, os NFEs são definitivamente úteis se você sabe que não vai lidar com navegadores antigos que os tornam um hash.As funções de nomenclatura são úteis se precisarem fazer referência a si mesmas (por exemplo, para chamadas recursivas). Na verdade, se você estiver passando uma expressão de função literal como um argumento diretamente para outra função, essa expressão de função não pode fazer referência a si mesma diretamente no modo estrito ES5, a menos que seja nomeada.
Por exemplo, considere este código:
Seria impossível escrever esse código de maneira tão limpa se a expressão de função passada para
setTimeout
fosse anônima; precisaríamos atribuí-lo a uma variável antes dasetTimeout
chamada. Dessa forma, com uma expressão de função nomeada, é ligeiramente mais curto e mais organizado.Era historicamente possível escrever código como este, mesmo usando uma expressão de função anônima, explorando
arguments.callee
...... mas
arguments.callee
está obsoleto e é totalmente proibido no modo estrito ES5. Portanto, o MDN aconselha:(ênfase minha)
fonte
Se uma função for especificada como Expressão de Função, ela pode receber um nome.
Estará disponível apenas dentro da função (exceto IE8-).
Este nome destina-se a uma chamada de função recursiva confiável, mesmo se for gravada em outra variável.
Além disso, o nome NFE (expressão de função nomeada) PODE ser substituído pelo
Object.defineProperty(...)
método da seguinte forma:Nota: isso não pode ser feito com a Declaração de Função. Este nome de função interna "especial" é especificado apenas na sintaxe de Expressão de Função.
fonte
Você deve sempre usar expressões de função nomeadas , por isso:
Você pode usar o nome dessa função quando precisar de recursão.
As funções anônimas não ajudam na depuração, pois você não pode ver o nome da função que causa problemas.
Quando você não nomeia uma função, mais tarde é mais difícil entender o que ela está fazendo. Dar-lhe um nome torna mais fácil de entender.
Aqui, por exemplo, como a barra de nomes é usada dentro de uma expressão de função, ela não é declarada no escopo externo. Com expressões de função nomeadas, o nome da expressão de função é incluído em seu próprio escopo.
fonte
Usar expressões de função nomeadas é melhor, quando você deseja poder fazer referência à função em questão sem ter que depender de recursos obsoletos, como
arguments.callee
.fonte