var functionName = function () {} vs function functionName () {}

Recentemente, comecei a manter o código JavaScript de outra pessoa. Estou corrigindo bugs, adicionando resources e também tentando arrumar o código e torná-lo mais consistente.

O desenvolvedor anterior usa duas maneiras de declarar funções e não consigo descobrir se há uma razão por trás disso ou não.

As duas maneiras são:

var functionOne = function() { // Some code }; 
 function functionTwo() { // Some code } 

Quais são as razões para usar esses dois methods diferentes e quais são os prós e contras de cada um deles? Existe alguma coisa que pode ser feita com um método que não pode ser feito com o outro?

   

A diferença é que functionOne é uma expressão de function e, portanto, apenas definida quando essa linha é alcançada, enquanto functionTwo é uma declaração de function e é definida assim que a function ou script circundante é executado (devido a içamento ).

Por exemplo, uma expressão de function:

 // TypeError: functionOne is not a function functionOne(); var functionOne = function() { console.log("Hello!"); }; 

Primeiro, quero corrigir Greg: a function abc(){} tem escopo – o nome abc é definido no escopo em que essa definição é encontrada. Exemplo:

 function xyz(){ function abc(){}; // abc is defined here... } // ...but not here 

Em segundo lugar, é possível combinar os dois estilos:

 var xyz = function abc(){}; 

xyz será definido como de costume, o abc é indefinido em todos os navegadores, mas o Internet Explorer não depende de sua definição. Mas será definido dentro de seu corpo:

 var xyz = function abc(){ // xyz is visible here // abc is visible here } // xyz is visible here // abc is undefined here 

Se você quiser alias funções em todos os navegadores, use este tipo de declaração:

 function abc(){}; var xyz = abc; 

Neste caso, ambos xyz e abc são aliases do mesmo object:

 console.log(xyz === abc); // prints "true" 

Uma razão convincente para usar o estilo combinado é o atributo “name” de objects de function ( não suportado pelo Internet Explorer ). Basicamente, quando você define uma function como

 function abc(){}; console.log(abc.name); // prints "abc" 

seu nome é atribuído automaticamente. Mas quando você define como

 var abc = function(){}; console.log(abc.name); // prints "" 

seu nome está vazio – criamos uma function anônima e a atribuímos a alguma variável.

Outro bom motivo para usar o estilo combinado é usar um nome interno curto para se referir a ele mesmo, fornecendo um nome longo e sem conflito para usuários externos:

 // Assume really.long.external.scoped is {} really.long.external.scoped.name = function shortcut(n){ // Let it call itself recursively: shortcut(n - 1); // ... // Let it pass itself as a callback: someFunction(shortcut); // ... } 

No exemplo acima, podemos fazer o mesmo com um nome externo, mas será muito pesado (e mais lento).

(Outra maneira de se referir a si mesmo é usar arguments.callee , que ainda é relativamente longo e não suportado no modo estrito.)

No fundo, o JavaScript trata as duas declarações de maneira diferente. Esta é uma declaração de function:

 function abc(){} 

abc aqui é definido em todos os lugares no escopo atual:

 // We can call it here abc(); // Works // Yet, it is defined down there. function abc(){} // We can call it again abc(); // Works 

Além disso, ele foi içado através de uma declaração de return :

 // We can call it here abc(); // Works return; function abc(){} 

Esta é uma expressão de function:

 var xyz = function(){}; 

xyz aqui é definido a partir do ponto de atribuição:

 // We can't call it here xyz(); // UNDEFINED!!! // Now it is defined xyz = function(){} // We can call it here xyz(); // works 

Declaração de function versus expressão de function é a verdadeira razão pela qual há uma diferença demonstrada por Greg.

Fato engraçado:

 var xyz = function abc(){}; console.log(xyz.name); // Prints "abc" 

Pessoalmente, eu prefiro a declaração de “expressão de function” porque desta forma eu posso controlar a visibilidade. Quando eu defino a function como

 var abc = function(){}; 

Eu sei que defini a function localmente. Quando eu defino a function como

 abc = function(){}; 

Eu sei que defini globalmente, desde que eu não definisse abc em nenhuma parte da cadeia de escopos. Esse estilo de definição é resiliente mesmo quando usado dentro de eval() . Enquanto a definição

 function abc(){}; 

depende do contexto e pode deixar você adivinhar onde está realmente definido, especialmente no caso de eval() – a resposta é: Depende do navegador.

Aqui está o resumo dos formulários padrão que criam funções: (Originalmente escrito para outra pergunta, mas adaptado depois de ser movido para a questão canônica.)

Termos:

  • ES5 : ECMAScript 5ª edição , 2009
  • ES2015 : ECMAScript 2015 (também conhecido como “ES6”)

A lista rápida:

  • Declaração de Função

  • function “Anônimo” Expressão (que, apesar do termo, às vezes cria funções com nomes)

  • function nomeada Expression

  • Inicializador de Função Acessor (ES5 +)

  • Expressão de Função de Seta (ES2015 +) (que, como expressões de function anônimas, não envolve um nome explícito e ainda pode criar funções com nomes)

  • Declaração de método no inicializador de object (ES2015 +)

  • Declarações de construtor e método na class (ES2015 +)

Declaração de Função

O primeiro formulário é uma declaração de function , que se parece com isso:

 function x() { console.log('x'); } 

Uma declaração de function é uma declaração ; não é uma declaração ou expressão. Como tal, você não o segue com um ; (embora isso seja inofensivo).

Uma declaração de function é processada quando a execução entra no contexto em que aparece, antes que qualquer código passo-a-passo seja executado. A function que ele cria recebe um nome próprio ( x no exemplo acima) e esse nome é colocado no escopo no qual a declaração aparece.

Como é processado antes de qualquer código passo-a-passo no mesmo contexto, você pode fazer coisas como esta:

 x(); // Works even though it's above the declaration function x() { console.log('x'); } 

Até ES2015, a especificação não cobria o que um mecanismo de JavaScript deveria fazer se você colocasse uma declaração de function dentro de uma estrutura de controle como try , if , switch , while , etc., assim:

 if (someCondition) { function foo() { // < ===== HERE THERE } // <===== BE DRAGONS } 

E como eles são processados antes de executar o código passo a passo, é difícil saber o que fazer quando estão em uma estrutura de controle.

Embora isso não tenha sido especificado até o ES2015, era uma extensão permitida para suportar declarações de function em blocos. Infelizmente (e inevitavelmente), diferentes motores fizeram coisas diferentes.

A partir do ES2015, a especificação diz o que fazer. Na verdade, ele oferece três coisas separadas para fazer:

  1. Se no modo solto não em um navegador da web, o mecanismo JavaScript deve fazer uma coisa
  2. Se estiver em modo solto em um navegador da Web, o mecanismo JavaScript deve fazer outra coisa
  3. Se no modo estrito (navegador ou não), o mecanismo de JavaScript deveria fazer outra coisa

As regras para os modos soltos são complicadas, mas no modo estrito , declarações de function em blocos são fáceis: elas são locais para o bloco (elas têm escopo de bloco , que também é novo no ES2015), e são içadas para o topo do bloco. Assim:

 "use strict"; if (someCondition) { foo(); // Works just fine function foo() { } } console.log(typeof foo); // "undefined" (`foo` is not in scope here // because it's not in the same block) 

Expressão da function "Anônimo"

A segunda forma comum é chamada de expressão de function anônima :

 var y = function () { console.log('y'); }; 

Como todas as expressões, é avaliado quando é atingido na execução passo a passo do código.

No ES5, a function criada não tem nome (é anônimo). No ES2015, a function é atribuída a um nome, se possível, inferindo-o do contexto. No exemplo acima, o nome seria y . Algo semelhante é feito quando a function é o valor de um inicializador de propriedade. (Para obter detalhes sobre quando isso acontece e as regras, pesquise SetFunctionName na especificação - ele aparece em todo o lugar.)

function nomeada Expression

A terceira forma é uma expressão de function nomeada ("NFE"):

 var z = function w() { console.log('zw') }; 

A function que isso cria tem um nome próprio ( w neste caso). Como todas as expressões, isso é avaliado quando é alcançado na execução passo a passo do código. O nome da function não é adicionado ao escopo no qual a expressão aparece; o nome está no escopo dentro da própria function:

 var z = function w() { console.log(typeof w); // "function" }; console.log(typeof w); // "undefined" 

Observe que os NFEs têm sido frequentemente uma fonte de bugs para implementações de JavaScript. O IE8 e versões anteriores, por exemplo, manipulam os NFEs de forma completamente incorreta , criando duas funções diferentes em dois momentos diferentes. As primeiras versões do Safari também tiveram problemas. A boa notícia é que as versões atuais dos navegadores (IE9 e acima, atual Safari) não têm mais esses problemas. (Mas, no momento em que escrevo, infelizmente, o IE8 continua sendo amplamente difundido e, portanto, o uso de NFEs com código para a web em geral ainda é problemático.)

Inicializador de Função Acessor (ES5 +)

Às vezes, as funções podem passar despercebidas; esse é o caso das funções do acessador . Aqui está um exemplo:

 var obj = { value: 0, get f() { return this.value; }, set f(v) { this.value = v; } }; console.log(obj.f); // 0 console.log(typeof obj.f); // "number" 

Note que quando usei a function, não usei () ! Isso é porque é uma function de access para uma propriedade. Obtemos e definimos a propriedade da maneira normal, mas nos bastidores, a function é chamada.

Você também pode criar funções de access com Object.defineProperty , Object.defineProperties e o segundo argumento menos conhecido para Object.create .

Expressão da Função de Seta (ES2015 +)

ES2015 nos traz a function de seta . Aqui está um exemplo:

 var a = [1, 2, 3]; var b = a.map(n => n * 2); console.log(b.join(", ")); // 2, 4, 6 

Veja que n => n * 2 coisa escondida na chamada map() ? Essa é uma function.

Algumas coisas sobre as funções das setas:

  1. Eles não têm this . Em vez disso, eles se aproximam do contexto em que estão definidos. (Eles também se fecham sobre arguments e, quando relevante, sobre super .) Isso significa que o que há dentro deles é o mesmo que this onde eles são criados e não podem ser alterados.

  2. Como você deve ter percebido acima, você não usa a function keyword; em vez disso, você usa => .

O exemplo n => n * 2 acima é uma forma deles. Se você tiver vários argumentos para passar a function, use parens:

 var a = [1, 2, 3]; var b = a.map((n, i) => n * i); console.log(b.join(", ")); // 0, 2, 6 

(Lembre-se que o Array#map passa a input como o primeiro argumento e o índice como o segundo.)

Em ambos os casos, o corpo da function é apenas uma expressão; o valor de retorno da function será automaticamente o resultado dessa expressão (você não usa um return explícito).

Se você estiver fazendo mais do que apenas uma única expressão, use {} e um return explícito (se precisar retornar um valor), como de costume:

 var a = [ {first: "Joe", last: "Bloggs"}, {first: "Albert", last: "Bloggs"}, {first: "Mary", last: "Albright"} ]; a = a.sort((a, b) => { var rv = a.last.localeCompare(b.last); if (rv === 0) { rv = a.first.localeCompare(b.first); } return rv; }); console.log(JSON.stringify(a)); 

A versão sem { ... } é chamada de uma function de seta com um corpo de expressão ou corpo conciso . (Também: Uma function de seta concisa .) Aquele com { ... } definindo o corpo é uma function de seta com um corpo de function . (Também: uma function de seta detalhada ).

Declaração de método no inicializador de object (ES2015 +)

O ES2015 permite uma forma mais curta de declarar uma propriedade que referencia uma function; Se parece com isso:

 var o = { foo() { } }; 

o equivalente em ES5 e anterior seria:

 var o = { foo: function foo() { } }; 

Declarações de construtor e método na class (ES2015 +)

O ES2015 nos traz a syntax de class , incluindo construtores e methods declarados:

 class Person { constructor(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; } getFullName() { return this.firstName + " " + this.lastName; } } 

Existem duas declarações de function acima: Uma para o construtor, que recebe o nome Person , e uma para getFullName , que é uma function atribuída a Person.prototype .

Falando sobre o contexto global, tanto a instrução var como uma FunctionDeclaration no final criarão uma propriedade não deletável no object global, mas o valor de ambos pode ser sobrescrito .

A diferença sutil entre as duas formas é que quando o processo de instanciação variável é executado (antes da execução do código) todos os identificadores declarados com var serão inicializados com undefined , e os utilizados pela declaração de FunctionDeclaration estarão disponíveis desde aquele momento, para exemplo:

  alert(typeof foo); // 'function', it's already available alert(typeof bar); // 'undefined' function foo () {} var bar = function () {}; alert(typeof bar); // 'function' 

A atribuição da bar FunctionExpression ocorre até o tempo de execução.

Uma propriedade global criada por um FunctionDeclaration pode ser sobrescrita sem problemas como um valor variável, por exemplo:

  function test () {} test = null; 

Outra diferença óbvia entre seus dois exemplos é que a primeira function não tem um nome, mas o segundo tem, o que pode ser realmente útil ao depurar (ou seja, inspecionar uma pilha de chamadas).

Sobre o seu primeiro exemplo editado ( foo = function() { alert('hello!'); }; ), É uma atribuição não declarada, eu recomendo que você sempre use a palavra-chave var .

Com uma atribuição, sem a instrução var , se o identificador referenciado não for encontrado na cadeia de escopo, ele se tornará uma propriedade excluível do object global.

Além disso, as tarefas não declaradas lançam um ReferenceError no ECMAScript 5 no Modo Estrito .

Uma leitura obrigatória:

  • Expressões de function nomeadas desmistificadas

Nota : Essa resposta foi mesclada de outra pergunta , na qual a principal dúvida e equívoco do OP era que os identificadores declarados com uma FunctionDeclaration , não poderiam ser sobrescritos, o que não é o caso.

Os dois trechos de código que você postou lá, para quase todos os propósitos, se comportarão da mesma maneira.

No entanto, a diferença no comportamento é que, com a primeira variante ( var functionOne = function() {} ), essa function só pode ser chamada após esse ponto no código.

Com a segunda variante ( function functionTwo() ), a function está disponível para o código que é executado acima de onde a function é declarada.

Isso ocorre porque, com a primeira variante, a function é atribuída à variável foo no tempo de execução. No segundo, a function é atribuída a esse identificador, foo , no tempo de análise.

Mais informação técnica

JavaScript tem três maneiras de definir funções.

  1. Seu primeiro snippet mostra uma expressão de function . Isso envolve usar o operador “function” para criar uma function – o resultado desse operador pode ser armazenado em qualquer variável ou propriedade de object. A expressão de function é poderosa dessa maneira. A expressão de function é freqüentemente chamada de “function anônima”, porque não precisa ter um nome,
  2. Seu segundo exemplo é uma declaração de function . Isso usa a instrução “function” para criar uma function. A function é disponibilizada no tempo de análise e pode ser chamada em qualquer lugar nesse escopo. Você ainda pode armazená-lo em uma propriedade de variável ou object posteriormente.
  3. A terceira maneira de definir uma function é o construtor “Function ()” , que não é mostrado em sua postagem original. Não é recomendado usar isso, pois funciona da mesma forma que o eval() , que tem seus problemas.

Uma explicação melhor para a resposta de Greg

 functionTwo(); function functionTwo() { } 

Por que não há erro? Sempre fomos ensinados que as expressões são executadas de cima para baixo (??)

Porque:

Declarações de function e declarações de variables ​​são sempre movidas ( hoisted ) de forma invisível para o topo do seu escopo de contenção pelo intérprete JavaScript. parameters de function e nomes definidos por linguagem já estão, obviamente, lá. ben cereja

Isso significa que o código assim:

 functionOne(); --------------- var functionOne; | is actually | functionOne(); var functionOne = function(){ | interpreted |--> }; | like | functionOne = function(){ --------------- }; 

Observe que a parte da atribuição das declarações não foi içada. Apenas o nome é içado.

Mas, no caso das declarações de function, todo o corpo da function também será içado :

 functionTwo(); --------------- function functionTwo() { | is actually | }; function functionTwo() { | interpreted |--> } | like | functionTwo(); --------------- 

Outros comentadores já cobriram a diferença semântica das duas variantes acima. Eu queria observar uma diferença estilística: somente a variação “atribuição” pode definir uma propriedade de outro object.

Eu costumo construir módulos JavaScript com um padrão como este:

 (function(){ var exports = {}; function privateUtil() { ... } exports.publicUtil = function() { ... }; return exports; })(); 

Com esse padrão, todas as suas funções públicas usarão atribuição, enquanto suas funções privadas usarão declaração.

(Note também que a atribuição deve exigir um ponto-e-vírgula após a declaração, enquanto a declaração a proíbe.)

Uma ilustração de quando preferir o primeiro método ao segundo é quando você precisa evitar a substituição das definições anteriores de uma function.

Com

 if (condition){ function myfunction(){ // Some code } } 

, esta definição de myfunction replaceá qualquer definição anterior, uma vez que será feita em tempo de análise.

Enquanto

 if (condition){ var myfunction = function (){ // Some code } } 

faz o trabalho correto de definir myfunction somente quando a condition é atendida.

Uma razão importante é adicionar uma e apenas uma variável como “Raiz” do seu namespace …

 var MyNamespace = {} MyNamespace.foo= function() { } 

ou

 var MyNamespace = { foo: function() { }, ... } 

Existem muitas técnicas para o namespace. Tornou-se mais importante com a infinidade de módulos JavaScript disponíveis.

Veja também Como declaro um namespace em JavaScript?

O içamento é a ação do intérprete de JavaScript de mover todas as declarações de variables ​​e funções para o topo do escopo atual.

No entanto, apenas as declarações reais são içadas. deixando atribuições onde estão.

  • As variables ​​/ funções declaradas dentro da página são globais e podem acessar em qualquer lugar da página.
  • As variables ​​/ funções declaradas dentro da function estão tendo escopo local. significa que eles estão disponíveis / acessados ​​dentro do corpo da function (escopo), eles não estão disponíveis fora do corpo da function.

Variável

Javascript é chamado de linguagem fracamente tipada. O que significa que variables ​​JavaScript podem conter valor de qualquer tipo de dados . O Javascript cuida automaticamente de alterar o tipo de variável com base no valor / literal fornecido durante o tempo de execução.

 global_Page = 10; var global_Page; « undefined « Integer literal, Number Type. ------------------- global_Page = 10; « Number global_Page = 'Yash'; | Interpreted | global_Page = 'Yash'; « String « String literal, String Type. « AS « global_Page = true; « Boolean var global_Page = true; | | global_Page = function (){ « function « Boolean Type ------------------- var local_functionblock; « undefined global_Page = function (){ local_functionblock = 777;« Number var local_functionblock = 777; }; // Assigning function as a data. }; 

Função

 function Identifier_opt ( FormalParameterList_opt ) { FunctionBody | sequence of statements « return; Default undefined « return 'some data'; } 
  • funções declaradas dentro da página são içadas para o topo da página com access global.
  • funções declaradas dentro do bloco de funções são içadas para o topo do bloco.
  • Valor de retorno padrão da function é ‘ indefinido ‘, Valor padrão da declaração de variável também ‘indefinido’

     Scope with respect to function-block global. Scope with respect to page undefined | not available. 

Declaração de Função

 function globalAccess() { function globalAccess() { } ------------------- } globalAccess(); | | function globalAccess() { « Re-Defined / overridden. localAccess(); « Hoisted As « function localAccess() { function globalAccess() { | | } localAccess(); ------------------- localAccess(); « function accessed with in globalAccess() only. function localAccess() { } } globalAccess(); } localAccess(); « ReferenceError as the function is not defined 

Expressão de Função

  10; « literal (10); « Expression (10).toString() -> '10' var a; a = 10; « Expression var a.toString() -> '10' (function invoke() { « Expression Function console.log('Self Invoking'); (function () { }); }) () -> 'Self Invoking' var f; f = function (){ « Expression var Function console.log('var Function'); f () -> 'var Function' }; 

Função atribuída à variável Exemplo:

 (function selfExecuting(){ console.log('IIFE - Immediately-Invoked Function Expression'); }()); var anonymous = function (){ console.log('anonymous function Expression'); }; var namedExpression = function for_InternalUSE(fact){ if(fact === 1){ return 1; } var localExpression = function(){ console.log('Local to the parent Function Scope'); }; globalExpression = function(){ console.log('creates a new global variable, then assigned this function.'); }; //return; //undefined. return fact * for_InternalUSE( fact - 1); }; namedExpression(); globalExpression(); 

javascript interpretado como

 var anonymous; var namedExpression; var globalExpression; anonymous = function (){ console.log('anonymous function Expression'); }; namedExpression = function for_InternalUSE(fact){ var localExpression; if(fact === 1){ return 1; } localExpression = function(){ console.log('Local to the parent Function Scope'); }; globalExpression = function(){ console.log('creates a new global variable, then assigned this function.'); }; return fact * for_InternalUSE( fact - 1); // DEFAULT UNDEFINED. }; namedExpression(10); globalExpression(); 

Você pode verificar declaração de function, teste de expressão em diferentes navegadores usando jsperf Test Runner


Classes de Função do Construtor ES5 : Objetos de function criados usando o Function.prototype.bind

JavaScript trata funções como objects de primeira class, portanto, sendo um object, você pode atribuir propriedades a uma function.

 function Shape(id) { // Function Declaration this.id = id; }; // Adding a prototyped method to a function. Shape.prototype.getID = function () { return this.id; }; Shape.prototype.setID = function ( id ) { this.id = id; }; var expFn = Shape; // Function Expression var funObj = new Shape( ); // Function Object funObj.hasOwnProperty('prototype'); // false funObj.setID( 10 ); console.log( funObj.getID() ); // 10 

Função de seta introduzida ES6: Uma expressão de function de seta tem uma syntax mais curta, elas são mais adequadas para funções que não são de método e não podem ser usadas como construtores.

ArrowFunction : ArrowParameters => ConciseBody .

 const fn = (item) => { return item & 1 ? 'Odd' : 'Even'; }; console.log( fn(2) ); // Even console.log( fn(3) ); // Odd 

Eu estou adicionando minha própria resposta só porque todo mundo já cobriu a parte de içamento completamente.

Eu me pergunto sobre qual caminho é melhor por um longo tempo agora, e graças a http://jsperf.com agora eu sei 🙂

insira a descrição da imagem aqui

Declarações de function são mais rápidas, e é isso que realmente importa no web dev, certo? 😉

A function declaration and a function expression assigned to a variable behave the same once the binding is established.

There is a difference however at how and when the function object is actually associated with its variable. This difference is due to the mechanism called variable hoisting in JavaScript.

Basically, all function declarations and variable declarations are hoisted to the top of the function in which the declaration occurs (this is why we say that JavaScript has function scope ).

  • When a function declaration is hoisted, the function body “follows” so when the function body is evaluated, the variable will immediately be bound to a function object.

  • When a variable declaration is hoisted, the initialization does not follow, but is “left behind”. The variable is initialized to undefined at the start of the function body, and will be assigned a value at its original location in the code. (Actually, it will be assigned a value at every location where a declaration of a variable with the same name occurs.)

The order of hoisting is also important: function declarations take precedence over variable declarations with the same name, and the last function declaration takes precedence over previous function declarations with the same name.

Some examples…

 var foo = 1; function bar() { if (!foo) { var foo = 10 } return foo; } bar() // 10 

Variable foo is hoisted to the top of the function, initialized to undefined , so that !foo is true , so foo is assigned 10 . The foo outside of bar ‘s scope plays no role and is untouched.

 function f() { return a; function a() {return 1}; var a = 4; function a() {return 2}} f()() // 2 function f() { return a; var a = 4; function a() {return 1}; function a() {return 2}} f()() // 2 

Function declarations take precedence over variable declarations, and the last function declaration “sticks”.

 function f() { var a = 4; function a() {return 1}; function a() {return 2}; return a; } f() // 4 

In this example a is initialized with the function object resulting from evaluating the second function declaration, and then is assigned 4 .

 var a = 1; function b() { a = 10; return; function a() {}} b(); a // 1 

Here the function declaration is hoisted first, declaring and initializing variable a . Next, this variable is assigned 10 . In other words: the assignment does not assign to outer variable a .

The first example is a function declaration:

 function abc(){} 

The second example is a function expression:

 var abc = function() {}; 

The main difference is how they are hoisted (lifted and declared). In the first example, the whole function declaration is hoisted. In the second example only the var ‘abc’ is hoisted, its value (the function) will be undefined, and the function itself remains at the position that it is declared.

To put it simply:

 //this will work abc(param); function abc(){} //this would fail abc(param); var abc = function() {} 

To study more about this topic I strongly recommend you this link

In terms of code maintenance cost, named functions are more preferable:

  • Independent from the place where they are declared (but still limited by scope).
  • More resistant to mistakes like conditional initialization (you are still able to override if wanted to).
  • The code becomes more readable by allocating local functions separately of scope functionality. Usually in the scope the functionality goes first, followed by declarations of local functions.
  • In a debugger you will clearly see the function name on the call stack instead of an “anonymous/evaluated” function.

I suspect more PROS for named functions are follow. And what is listed as an advantage of named functions is a disadvantage for anonymous ones.

Historically, anonymous functions appeared from the inability of JavaScript as a language to list members with named functions:

 { member:function() { /* How do I make "this.member" a named function? */ } } 

I use the variable approach in my code for a very specific reason, the theory of which has been covered in an abstract way above, but an example might help some people like me, with limited JavaScript expertise.

I have code that I need to run with 160 independently-designed brandings. Most of the code is in shared files, but branding-specific stuff is in a separate file, one for each branding.

Some brandings require specific functions, and some do not. Sometimes I have to add new functions to do new branding-specific things. I am happy to change the shared coded, but I don’t want to have to change all 160 sets of branding files.

By using the variable syntax, I can declare the variable (a function pointer essentially) in the shared code and either assign a trivial stub function, or set to null.

The one or two brandings that need a specific implementation of the function can then define their version of the function and assign this to the variable if they want, and the rest do nothing. I can test for a null function before I execute it in the shared code.

From people’s comments above, I gather it may be possible to redefine a static function too, but I think the variable solution is nice and clear.

In computer science terms, we talk about anonymous functions and named functions. I think the most important difference is that an anonymous function is not bound to an name, hence the name anonymous function. In JavaScript it is a first class object dynamically declared at runtime.

For more information on anonymous functions and lambda calculus, Wikipedia is a good start ( http://en.wikipedia.org/wiki/Anonymous_function ).

Greg’s Answer is good enough, but I still would like to add something to it that I learned just now watching Douglas Crockford’s videos.

Function expression:

 var foo = function foo() {}; 

Function statement:

 function foo() {}; 

The function statement is just a shorthand for var statement with a function value.

So

 function foo() {}; 

expands to

 var foo = function foo() {}; 

Which expands further to:

 var foo = undefined; foo = function foo() {}; 

And they are both hoisted to the top of the code.

Screenshot from video

@EugeneLazutkin gives an example where he names an assigned function to be able to use shortcut() as an internal reference to itself. John Resig gives another example – copying a recursive function assigned to another object in his Learning Advanced Javascript tutorial. While assigning functions to properties isn’t strictly the question here, I recommend actively trying the tutorial out – run the code by clicking the button in the upper right corner, and double click the code to edit to your liking.

Examples from the tutorial: recursive calls in yell() :

Tests fail when the original ninja object is removed. (page 13)

 var ninja = { yell: function(n){ return n > 0 ? ninja.yell(n-1) + "a" : "hiy"; } }; assert( ninja.yell(4) == "hiyaaaa", "A single object isn't too bad, either." ); var samurai = { yell: ninja.yell }; var ninja = null; try { samurai.yell(4); } catch(e){ assert( false, "Uh, this isn't good! Where'd ninja.yell go?" ); } 

If you name the function that will be called recursively, the tests will pass. (page 14)

 var ninja = { yell: function yell(n){ return n > 0 ? yell(n-1) + "a" : "hiy"; } }; assert( ninja.yell(4) == "hiyaaaa", "Works as we would expect it to!" ); var samurai = { yell: ninja.yell }; var ninja = {}; assert( samurai.yell(4) == "hiyaaaa", "The method correctly calls itself." ); 

Another difference that is not mentioned in the other answers is that if you use the anonymous function

 var functionOne = function() { // Some code }; 

and use that as a constructor as in

 var one = new functionOne(); 

then one.constructor.name will not be defined. Function.name is non-standard but is supported by Firefox, Chrome, other Webkit-derived browsers and IE 9+.

Com

 function functionTwo() { // Some code } two = new functionTwo(); 

it is possible to retrieve the name of the constructor as a string with two.constructor.name .

If you would use those functions to create objects, you would get:

 var objectOne = new functionOne(); console.log(objectOne.__proto__); // prints "Object {}" because constructor is an anonymous function var objectTwo = new functionTwo(); console.log(objectTwo.__proto__); // prints "functionTwo {}" because constructor is a named function 

I’m listing out the differences below:

  1. A function declaration can be placed anywhere in the code. Even if it is invoked before the definition appears in code, it gets executed as function declaration is committed to memory or in a way it is hoisted up, before any other code in the page starts execution.

    Take a look at the function below:

     function outerFunction() { function foo() { return 1; } return foo(); function foo() { return 2; } } alert(outerFunction()); // Displays 2 

    This is because, during execution, it looks like:-

     function foo() { // The first function declaration is moved to top return 1; } function foo() { // The second function declaration is moved to top return 2; } function outerFunction() { return foo(); } alert(outerFunction()); //So executing from top to bottom, //the last foo() returns 2 which gets displayed 

    A function expression, if not defined before calling it, will result in an error. Also, here the function definition itself is not moved to the top or committed to memory like in the function declarations. But the variable to which we assign the function gets hoisted up and undefined gets assigned to it.

    Same function using function expressions:

     function outerFunction() { var foo = function() { return 1; } return foo(); var foo = function() { return 2; } } alert(outerFunction()); // Displays 1 

    This is because during execution, it looks like:

     function outerFunction() { var foo = undefined; var foo = undefined; foo = function() { return 1; }; return foo (); foo = function() { // This function expression is not reachable return 2; }; } alert(outerFunction()); // Displays 1 
  2. It is not safe to write function declarations in non-function blocks like if because they won’t be accessible.

     if (test) { function x() { doSomething(); } } 
  3. Named function expression like the one below, may not work in Internet Explorer browsers prior to version 9.

     var today = function today() {return new Date()} 

The first one (function doSomething(x)) should be part of an object notation.

The second one ( var doSomething = function(x){ alert(x);} ) is simply creating an anonymous function and assigning it to a variable, doSomething . So doSomething() will call the function.

You may want to know what a function declaration and function expression is.

A function declaration defines a named function variable without requiring variable assignment. Function declarations occur as standalone constructs and cannot be nested within non-function blocks.

 function foo() { return 3; } 

ECMA 5 (13.0) defines the syntax as
function Identifier ( FormalParameterList opt ) { FunctionBody }

In above condition the function name is visible within its scope and the scope of its parent (otherwise it would be unreachable).

And in a function expression

A function expression defines a function as a part of a larger expression syntax (typically a variable assignment ). Functions defined via functions expressions can be named or anonymous. Function expressions should not start with “function”.

 // Anonymous function expression var a = function() { return 3; } // Named function expression var a = function foo() { return 3; } // Self-invoking function expression (function foo() { alert("hello!"); })(); 

ECMA 5 (13.0) defines the syntax as
function Identifier opt ( FormalParameterList opt ) { FunctionBody }

In light of the “named functions show up in stack traces” argument, modern JavaScript engines are actually quite capable of representing anonymous functions.

As of this writing, V8, SpiderMonkey, Chakra and Nitro always refer to named functions by their names. They almost always refer to an anonymous function by its identifier if it has one.

SpiderMonkey can figure out the name of an anonymous function returned from another function. The rest can’t.

If you really, really wanted your iterator and success callbacks to show up in the trace, you could name those too…

 [].forEach(function iterator() {}); 

But for the most part it’s not worth stressing over.

Harness ( Fiddle )

 'use strict'; var a = function () { throw new Error(); }, b = function b() { throw new Error(); }, c = function d() { throw new Error(); }, e = { f: a, g: b, h: c, i: function () { throw new Error(); }, j: function j() { throw new Error(); }, k: function l() { throw new Error(); } }, m = (function () { return function () { throw new Error(); }; }()), n = (function () { return function n() { throw new Error(); }; }()), o = (function () { return function p() { throw new Error(); }; }()); console.log([a, b, c].concat(Object.keys(e).reduce(function (values, key) { return values.concat(e[key]); }, [])).concat([m, n, o]).reduce(function (logs, func) { try { func(); } catch (error) { return logs.concat('func.name: ' + func.name + '\n' + 'Trace:\n' + error.stack); // Need to manually log the error object in Nitro. } }, []).join('\n\n')); 

V8

 func.name: Trace: Error at a (http://localhost:8000/test.js:4:11) at http://localhost:8000/test.js:47:9 at Array.reduce (native) at http://localhost:8000/test.js:44:27 func.name: b Trace: Error at b (http://localhost:8000/test.js:7:15) at http://localhost:8000/test.js:47:9 at Array.reduce (native) at http://localhost:8000/test.js:44:27 func.name: d Trace: Error at d (http://localhost:8000/test.js:10:15) at http://localhost:8000/test.js:47:9 at Array.reduce (native) at http://localhost:8000/test.js:44:27 func.name: Trace: Error at a (http://localhost:8000/test.js:4:11) at http://localhost:8000/test.js:47:9 at Array.reduce (native) at http://localhost:8000/test.js:44:27 func.name: b Trace: Error at b (http://localhost:8000/test.js:7:15) at http://localhost:8000/test.js:47:9 at Array.reduce (native) at http://localhost:8000/test.js:44:27 func.name: d Trace: Error at d (http://localhost:8000/test.js:10:15) at http://localhost:8000/test.js:47:9 at Array.reduce (native) at http://localhost:8000/test.js:44:27 func.name: Trace: Error at ei (http://localhost:8000/test.js:17:19) at http://localhost:8000/test.js:47:9 at Array.reduce (native) at http://localhost:8000/test.js:44:27 func.name: j Trace: Error at j (http://localhost:8000/test.js:20:19) at http://localhost:8000/test.js:47:9 at Array.reduce (native) at http://localhost:8000/test.js:44:27 func.name: l Trace: Error at l (http://localhost:8000/test.js:23:19) at http://localhost:8000/test.js:47:9 at Array.reduce (native) at http://localhost:8000/test.js:44:27 func.name: Trace: Error at http://localhost:8000/test.js:28:19 at http://localhost:8000/test.js:47:9 at Array.reduce (native) at http://localhost:8000/test.js:44:27 func.name: n Trace: Error at n (http://localhost:8000/test.js:33:19) at http://localhost:8000/test.js:47:9 at Array.reduce (native) at http://localhost:8000/test.js:44:27 func.name: p Trace: Error at p (http://localhost:8000/test.js:38:19) at http://localhost:8000/test.js:47:9 at Array.reduce (native) at http://localhost:8000/test.js:44:27 test.js:42 

SpiderMonkey

 func.name: Trace: a@http://localhost:8000/test.js:4:5 @http://localhost:8000/test.js:47:9 @http://localhost:8000/test.js:54:1 func.name: b Trace: b@http://localhost:8000/test.js:7:9 @http://localhost:8000/test.js:47:9 @http://localhost:8000/test.js:54:1 func.name: d Trace: d@http://localhost:8000/test.js:10:9 @http://localhost:8000/test.js:47:9 @http://localhost:8000/test.js:54:1 func.name: Trace: a@http://localhost:8000/test.js:4:5 @http://localhost:8000/test.js:47:9 @http://localhost:8000/test.js:54:1 func.name: b Trace: b@http://localhost:8000/test.js:7:9 @http://localhost:8000/test.js:47:9 @http://localhost:8000/test.js:54:1 func.name: d Trace: d@http://localhost:8000/test.js:10:9 @http://localhost:8000/test.js:47:9 @http://localhost:8000/test.js:54:1 func.name: Trace: ei@http://localhost:8000/test.js:17:13 @http://localhost:8000/test.js:47:9 @http://localhost:8000/test.js:54:1 func.name: j Trace: j@http://localhost:8000/test.js:20:13 @http://localhost:8000/test.js:47:9 @http://localhost:8000/test.js:54:1 func.name: l Trace: l@http://localhost:8000/test.js:23:13 @http://localhost:8000/test.js:47:9 @http://localhost:8000/test.js:54:1 func.name: Trace: m 

Chakra

 func.name: undefined Trace: Error at a (http://localhost:8000/test.js:4:5) at Anonymous function (http://localhost:8000/test.js:47:9) at Global code (http://localhost:8000/test.js:42:1) func.name: undefined Trace: Error at b (http://localhost:8000/test.js:7:9) at Anonymous function (http://localhost:8000/test.js:47:9) at Global code (http://localhost:8000/test.js:42:1) func.name: undefined Trace: Error at d (http://localhost:8000/test.js:10:9) at Anonymous function (http://localhost:8000/test.js:47:9) at Global code (http://localhost:8000/test.js:42:1) func.name: undefined Trace: Error at a (http://localhost:8000/test.js:4:5) at Anonymous function (http://localhost:8000/test.js:47:9) at Global code (http://localhost:8000/test.js:42:1) func.name: undefined Trace: Error at b (http://localhost:8000/test.js:7:9) at Anonymous function (http://localhost:8000/test.js:47:9) at Global code (http://localhost:8000/test.js:42:1) func.name: undefined Trace: Error at d (http://localhost:8000/test.js:10:9) at Anonymous function (http://localhost:8000/test.js:47:9) at Global code (http://localhost:8000/test.js:42:1) func.name: undefined Trace: Error at ei (http://localhost:8000/test.js:17:13) at Anonymous function (http://localhost:8000/test.js:47:9) at Global code (http://localhost:8000/test.js:42:1) func.name: undefined Trace: Error at j (http://localhost:8000/test.js:20:13) at Anonymous function (http://localhost:8000/test.js:47:9) at Global code (http://localhost:8000/test.js:42:1) func.name: undefined Trace: Error at l (http://localhost:8000/test.js:23:13) at Anonymous function (http://localhost:8000/test.js:47:9) at Global code (http://localhost:8000/test.js:42:1) func.name: undefined Trace: Error at Anonymous function (http://localhost:8000/test.js:28:13) at Anonymous function (http://localhost:8000/test.js:47:9) at Global code (http://localhost:8000/test.js:42:1) func.name: undefined Trace: Error at n (http://localhost:8000/test.js:33:13) at Anonymous function (http://localhost:8000/test.js:47:9) at Global code (http://localhost:8000/test.js:42:1) func.name: undefined Trace: Error at p (http://localhost:8000/test.js:38:13) at Anonymous function (http://localhost:8000/test.js:47:9) at Global code (http://localhost:8000/test.js:42:1) 

Nitro

 func.name: Trace: a@http://localhost:8000/test.js:4:22 http://localhost:8000/test.js:47:13 reduce@[native code] global code@http://localhost:8000/test.js:44:33 func.name: b Trace: b@http://localhost:8000/test.js:7:26 http://localhost:8000/test.js:47:13 reduce@[native code] global code@http://localhost:8000/test.js:44:33 func.name: d Trace: d@http://localhost:8000/test.js:10:26 http://localhost:8000/test.js:47:13 reduce@[native code] global code@http://localhost:8000/test.js:44:33 func.name: Trace: a@http://localhost:8000/test.js:4:22 http://localhost:8000/test.js:47:13 reduce@[native code] global code@http://localhost:8000/test.js:44:33 func.name: b Trace: b@http://localhost:8000/test.js:7:26 http://localhost:8000/test.js:47:13 reduce@[native code] global code@http://localhost:8000/test.js:44:33 func.name: d Trace: d@http://localhost:8000/test.js:10:26 http://localhost:8000/test.js:47:13 reduce@[native code] global code@http://localhost:8000/test.js:44:33 func.name: Trace: i@http://localhost:8000/test.js:17:30 http://localhost:8000/test.js:47:13 reduce@[native code] global code@http://localhost:8000/test.js:44:33 func.name: j Trace: j@http://localhost:8000/test.js:20:30 http://localhost:8000/test.js:47:13 reduce@[native code] global code@http://localhost:8000/test.js:44:33 func.name: l Trace: l@http://localhost:8000/test.js:23:30 http://localhost:8000/test.js:47:13 reduce@[native code] global code@http://localhost:8000/test.js:44:33 func.name: Trace: http://localhost:8000/test.js:28:30 http://localhost:8000/test.js:47:13 reduce@[native code] global code@http://localhost:8000/test.js:44:33 func.name: n Trace: n@http://localhost:8000/test.js:33:30 http://localhost:8000/test.js:47:13 reduce@[native code] global code@http://localhost:8000/test.js:44:33 func.name: p Trace: p@http://localhost:8000/test.js:38:30 http://localhost:8000/test.js:47:13 reduce@[native code] global code@http://localhost:8000/test.js:44:33 

In JavaScript there are two ways to create functions:

  1. Function declaration:

     function fn(){ console.log("Hello"); } fn(); 

    This is very basic, self-explanatory, used in many languages and standard across C family of languages. We declared a function defined it and executed it by calling it.

    What you should be knowing is that functions are actually objects in JavaScript; internally we have created an object for above function and given it a name called fn or the reference to the object is stored in fn. Functions are objects in JavaScript; an instance of function is actually an object instance.

  2. Function expression:

     var fn=function(){ console.log("Hello"); } fn(); 

    JavaScript has first-class functions, that is, create a function and assign it to a variable just like you create a string or number and assign it to a variable. Here, the fn variable is assigned to a function. The reason for this concept is functions are objects in JavaScript; fn is pointing to the object instance of the above function. We have initialized a function and assigned it to a variable. It’s not executing the function and assigning the result.

Reference: JavaScript function declaration syntax: var fn = function() {} vs function fn() {}

Both are different ways of defining a function. The difference is how the browser interprets and loads them into an execution context.

The first case is of function expressions which loads only when the interpreter reaches that line of code. So if you do it like the following, you will get an error that the functionOne is not a function .

 functionOne(); var functionOne = function() { // Some code }; 

The reason is that on the first line no value is assigned to functionOne, and hence it is undefined. We are trying to call it as a function, and hence we are getting an error.

On the second line we are assigning the reference of an anonymous function to functionOne.

The second case is of function declarations that loads before any code is executed. So if you do like the following you won’t get any error as the declaration loads before code execution.

 functionOne(); function functionOne() { // Some code } 

About performance:

New versions of V8 introduced several under-the-hood optimizations and so did SpiderMonkey .

There is almost no difference now between expression and declaration.
Function expression appears to be faster now.

Chrome 62.0.3202 Chrome test

FireFox 55 Firefox test

Chrome Canary 63.0.3225 Chrome Canary test

Anonymous function expressions appear to have better performance against Named function expression.

Firefox Firefox named_anonymous Chrome Canary Chrome canary named_anonymous Chrome Chrome named_anonymous

There are three noteworthy comparisons between the two different declarations of functions as listed below.

  1. Availability (scope) of the function

The following works because function add() is scoped to the nearest block:

 try { console.log("Success: ", add(1, 1)); } catch(e) { console.log("ERROR: " + e); } function add(a, b){ return a + b; } 

They are pretty similar with some small differences, first one is a variable which assigned to an anonymous function (Function Declaration) and second one is the normal way to create a function in JavaScript(Anonymous function Declaration), both has usage, cons and pros:

1. Function Expression

 var functionOne = function() { // Some code }; 

A Function Expression defines a function as a part of a larger expression syntax (typically a variable assignment ). Functions defined via Functions Expressions can be named or anonymous. Function Expressions must not start with “function” (hence the parentheses around the self invoking example below).

Assign a variable to a function, means no Hoisting, as we know functions in JavaScript can Hoist, means they can be called before they get declared, while variables need to be declared before getting access to them, so means in this case we can not access the function before where it’s declared, also it could be a way that you write your functions, for the functions which return another function, this kind of declaration could make sense, also in ECMA6 & above you can assign this to an arrow function which can be used to call anonymous functions, also this way of declaring is a better way to create Constructor functions in JavaScript.

2. Function Declaration

 function functionTwo() { // Some code } 

A Function Declaration defines a named function variable without requiring variable assignment. Function Declarations occur as standalone constructs and cannot be nested within non-function blocks. It’s helpful to think of them as siblings of Variable Declarations. Just as Variable Declarations must start with “var”, Function Declarations must begin with “function”.

This is the normal way of calling a function in JavaScript, this function can be called before you even declare it as in JavaScript all functions get Hoisted, but if you have ‘use strict’ this won’t Hoist as expected, it’s a good way to call all normal functions which are not big in lines and neither are a constructor function.

Also, if you need more info about how hoisting works in JavaScript, visit the link below:

https://developer.mozilla.org/en-US/docs/Glossary/Hoisting

This is just two possible ways of declaring functions, and in the second way, you can use the function before declaration.

new Function() can be used to pass the function’s body in a string. And hence this can be used to create dynamic functions. Also passing the script without executing the script.

 var func = new Function("x", "y", "return x*y;"); function secondFunction(){ var result; result = func(10,20); console.log ( result ); } secondFunction()