Qual é a diferença entre uma expressão de function vs declaração em JavaScript?

Qual é a diferença entre as seguintes linhas de código?

//Function declaration function foo() { return 5; } //Anonymous function expression var foo = function() { return 5; } //Named function expression var foo = function foo() { return 5; } 
  • O que é uma expressão de function nomeada / anônima?
  • O que é uma function declarada?
  • Como os navegadores lidam com essas construções de maneira diferente?

O que as respostas a uma pergunta semelhante ( var functionName = function () {} versus function functionName () {} ) não são exatamente corretas?

Eles são realmente muito parecidos. Como você os chama é exatamente o mesmo. A diferença está em como o navegador os carrega no contexto de execução.

As declarações de function são carregadas antes de qualquer código ser executado.

As expressões de function só são carregadas quando o intérprete atinge essa linha de código.

Então, se você tentar chamar uma expressão de function antes de ser carregada, você receberá um erro! Se você chamar uma declaração de function, ela sempre funcionará, porque nenhum código pode ser chamado até que todas as declarações sejam carregadas.

Exemplo: Expressão de Função

 alert(foo()); // ERROR! foo wasn't loaded yet var foo = function() { return 5; } 

Exemplo: declaração de function

 alert(foo()); // Alerts 5. Declarations are loaded before any code can run. function foo() { return 5; } 

Quanto à segunda parte da sua pergunta:

var foo = function foo() { return 5; } var foo = function foo() { return 5; } é realmente o mesmo que os outros dois. É só que essa linha de código costumava causar um erro no safari, embora isso não aconteça mais.

Declaração de Função

 function foo() { ... } 

Por causa da function de içamento , a function declarada dessa maneira pode ser chamada após e antes da definição.

Expressão de Função

  1. Expressão de function nomeada

     var foo = function bar() { ... } 
  2. Expressão de Função Anônima

     var foo = function() { ... } 

foo() pode ser chamado após a criação.

Expressão de Função Imediatamente Invocada (IIFE)

 (function() { ... }()); 

Conclusão

Crockford recomenda usar a expressão de function porque deixa claro que foo é uma variável que contém um valor de function. Bem, pessoalmente, prefiro usar a Declaração, a menos que haja uma razão para Expressão.

Em relação à 3ª definição:

 var foo = function foo() { return 5; } 

Aqui está um exemplo que mostra como usar a possibilidade de chamada recursiva:

 a = function b(i) { if (i>10) { return i; } else { return b(++i); } } console.log(a(5)); // outputs 11 console.log(a(10)); // outputs 11 console.log(a(11)); // outputs 11 console.log(a(15)); // outputs 15 

Edit: exemplo mais interessante com fechamentos:

 a = function(c) { return function b(i){ if (i>c) { return i; } return b(++i); } } d = a(5); console.log(d(3)); // outputs 6 console.log(d(8)); // outputs 8 

A primeira instrução depende do contexto em que é declarada.

Se for declarado no contexto global, ele criará uma variável global implícita chamada “foo”, que será uma variável que aponta para a function. Assim, a chamada de function “foo ()” pode ser feita em qualquer lugar no seu programa de javascript.

Se a function for criada em um encerramento, ela criará uma variável local implícita chamada “foo”, que você pode usar para invocar a function dentro do fechamento com “foo ()”

EDITAR:

Eu deveria ter dito também que as instruções de function (A primeira) são analisadas antes das expressões de function (A outra 2). Isso significa que, se você declarar a function na parte inferior do script, ainda poderá usá-la na parte superior. Expressões de function só são avaliadas quando são atingidas pelo código de execução.

END EDIT

As declarações 2 e 3 são praticamente equivalentes entre si. Novamente, se usados ​​no contexto global, eles criarão variables ​​globais e, se usados ​​em um encerramento, criarão variables ​​locais. No entanto, vale a pena observar que a instrução 3 irá ignorar o nome da function, portanto, você poderia chamar a function de qualquer coisa. Assim sendo

 var foo = function foo() { return 5; } 

É o mesmo que

 var foo = function fooYou() { return 5; } 

Embora a diferença completa seja mais complicada, a única diferença que me preocupa é quando a máquina cria o object de function. Que no caso de declarações é antes que qualquer instrução seja executada, mas depois que um corpo de instrução é invocado (seja o corpo do código global ou uma subfunction), e no caso de expressões é quando a instrução em que é executada é executada. Fora isso, para todos os efeitos, os navegadores os tratam da mesma forma.

Para ajudá-lo a entender, dê uma olhada neste teste de desempenho que eliminou uma suposição que eu fiz de funções declaradas internamente, não precisando ser recriadas pela máquina quando a function externa é invocada. É uma vergonha também, pois gostei de escrever código dessa maneira.