Function Expression vs Declaration: o que escolher em JavaScript?

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Por que essa questão incomoda até desenvolvedores experientes?

\n

Se você já escreveu em JavaScript, certamente já encontrou ambas as formas de declarar funções. Elas parecem semelhantes, mas se comportam de maneiras completamente diferentes. No Stack Overflow, essa pergunta acumulou milhares de visualizações e dezenas de páginas de discussão. Por quê? Porque a falta de compreensão da diferença entre var functionName = function() {} e function functionName() {} leva a bugs difíceis de detectar.

\n

Hoje vamos entender esse tópico de uma vez por todas. Você aprenderá o que é function declaration e function expression, como funciona o hoisting e quando usar cada abordagem. Vamos lá!

\n\n

O que está por trás da sintaxe?

\n

Vamos começar pelo básico. A primeira opção é a Function Declaration (declaração de função):

\n
function greet() {\n    console.log('Olá!');\n}
\n

A segunda é a Function Expression (expressão de função):

\n
const greet = function() {\n    console.log('Olá!');\n};
\n

Observe: no primeiro caso, a função tem um nome e está no início da linha. No segundo, atribuímos uma função anônima à variável greet. Mas o mais interessante começa quando vemos como o JavaScript processa essas declarações.

\n\n

A principal diferença: Hoisting (elevação)

\n

Hoisting é um mecanismo do JavaScript no qual as declarações de variáveis e funções são movidas para o topo de seu escopo antes da execução do código. Mas ele funciona de forma diferente para declaration e expression.

\n\n

Function Declaration é elevada por completo

\n

Quando você usa function functionName() {}, o JavaScript "eleva" toda a declaração da função para o topo. Isso significa que você pode chamar a função antes de ela ser declarada no código:

\n
sayHello(); // "Olá!"\n\nfunction sayHello() {\n    console.log('Olá!');\n}
\n

O código será executado sem erros. Isso é conveniente, mas pode confundir iniciantes.

\n\n

Function Expression não é elevada

\n

Com var functionName = function() {} a história é diferente. Apenas a declaração da variável é elevada, mas não o seu valor. A função permanece no lugar:

\n
sayHello(); // TypeError: sayHello is not a function\n\nvar sayHello = function() {\n    console.log('Olá!');\n};
\n

Por que isso acontece? Porque var eleva a declaração da variável sayHello (com o valor undefined), e a atribuição da função ocorre apenas na linha da expressão. Portanto, antes dessa linha, sayHello é undefined, e tentar chamá-lo como função resulta em erro.

\n\n

A propósito, se você substituir var por let ou const, o erro será diferente — ReferenceError: Cannot access 'sayHello' before initialization. Isso está relacionado ao fato de que let e const não são inicializados até o momento da declaração (a chamada "zona morta temporal").

\n\n

Escopo: outro ponto de atenção

\n

Tanto a function declaration quanto a function expression seguem as regras de escopo. Mas há uma nuance.

\n\n

Function Declaration é visível dentro do bloco

\n

Embora a function declaration seja elevada, seu escopo é limitado ao bloco (no modo estrito):

\n
'use strict';\nif (true) {\n    function greet() {\n        console.log('Dentro do bloco');\n    }\n    greet(); // "Dentro do bloco"\n}\ngreet(); // ReferenceError: greet is not defined (no modo estrito)
\n

No modo não estrito, essa declaração "vaza" para fora, mas não é recomendável confiar nisso.

\n\n

Function Expression vive em sua variável

\n

Com a function expression, tudo é previsível: a função só está disponível onde a variável está acessível. Se mover

Blogs

Book Recommendations