javascript expression - var functionName=function(){}vs função functionName(){}



declaration this (25)

O primeiro exemplo é uma declaração de função:

function abc(){}

O segundo exemplo é uma expressão de função:

var abc = function() {};

A principal diferença é como eles são içados (levantados e declarados). No primeiro exemplo, a declaração da função inteira é hasteada. No segundo exemplo, apenas o var 'abc' é içado, seu valor (a função) será indefinido e a própria função permanece na posição em que é declarada.

Para simplificar:

//this will work
abc(param);
function abc(){}

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

Para estudar mais sobre este tópico, recomendo vivamente este link

Recentemente, comecei a manter o código JavaScript de outra pessoa. Estou corrigindo bugs, adicionando recursos 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 métodos 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?


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:

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 função 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 objeto (ES2015 +)

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

Declaração de Função

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

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

Uma declaração de função é 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 função é processada quando a execução entra no contexto em que aparece, antes que qualquer código passo-a-passo seja executado. A função 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 função 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 função 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 função 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 função 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 função criada não tem nome (é anônimo). No ES2015, a função é atribuída a um nome, se possível, inferindo-o do contexto. No exemplo acima, o nome seria y . Algo semelhante é feito quando a função é 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 função nomeada ("NFE"):

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

A função 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 função não é adicionado ao escopo no qual a expressão aparece; o nome está no escopo dentro da própria função:

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 função, não usei () ! Isso é porque é uma função de acesso para uma propriedade. Obtemos e definimos a propriedade da maneira normal, mas nos bastidores, a função é chamada.

Você também pode criar funções de acesso 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 função 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 função.

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 função, 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 entrada como o primeiro argumento e o índice como o segundo.)

Em ambos os casos, o corpo da função é apenas uma expressão; o valor de retorno da função 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 função de seta com um corpo de expressão ou corpo conciso . (Também: Uma função de seta concisa .) Aquele com { ... } definindo o corpo é uma função de seta com um corpo de função . (Também: uma função de seta detalhada ).

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

O ES2015 permite uma forma mais curta de declarar uma propriedade que referencia uma função; 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 sintaxe de class , incluindo construtores e métodos declarados:

class Person {
    constructor(firstName, lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    getFullName() {
        return this.firstName + " " + this.lastName;
    }
}

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


Esta é apenas duas maneiras possíveis de declarar funções, e da segunda maneira, você pode usar a função antes da declaração.


dá um exemplo onde ele nomeia uma função atribuída para poder usarshortcut() como uma referência interna para si mesma. John Resig dá outro exemplo - copiando uma função recursiva atribuída a outro objeto em seu tutorial Aprendendo sobre Javascript Avançado . Embora designar funções para propriedades não seja estritamente a questão aqui, recomendo ativamente testar o tutorial - execute o código clicando no botão no canto superior direito e clique duas vezes no código para editá-lo ao seu gosto.

Exemplos do tutorial: chamadas recursivas em yell():

Os testes falham quando o objeto ninja original é removido. (página 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?" ); 
}

Se você nomear a função que será chamada recursivamente, os testes serão aprovados. (página 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." );

Falando sobre o contexto global, tanto a instrução var como uma FunctionDeclaration no final criarão uma propriedade não deletável no objeto 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 função 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 objeto global.

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

Uma leitura obrigatória:

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.


Hoisting é a ação do intérprete de JavaScript de mover todas as declarações de variáveis ​​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 variáveis ​​/ funções declaradas dentro da página são globais e podem acessar em qualquer lugar da página.
  • As variáveis ​​/ funções declaradas dentro da função estão tendo escopo local. significa que eles estão disponíveis / acessados ​​dentro do corpo da função (escopo), eles não estão disponíveis fora do corpo da função.

Variable

Javascript é chamado de linguagem fracamente tipada. O que significa que variáveis ​​JavaScript podem conter valor de qualquer tipo de Data-Type . 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 acesso 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 função é ' undefined ', Valor padrão da declaração de Variable 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 função, teste de expressão em diferentes navegadores usando jsperf Test Runner

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

JavaScript trata funções como objetos de primeira classe, portanto, sendo um objeto, você pode atribuir propriedades a uma função.

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 função de seta tem uma sintaxe 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

Estou listando as diferenças abaixo:

  1. Uma declaração de função pode ser colocada em qualquer lugar no código. Mesmo se for invocado antes que a definição apareça no código, ele será executado quando a declaração da função for confirmada na memória ou de uma forma que seja hasteada, antes que qualquer outro código na página inicie a execução.

    Dê uma olhada na função abaixo:

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

    Isso porque, durante a execução, parece que: -

    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
    

    Uma expressão de função, se não definida antes de chamá-la, resultará em um erro. Além disso, aqui a definição da função em si não é movida para o início ou confirmada para a memória como nas declarações de função. Mas a variável à qual atribuímos a função é hasteada e indefinida é atribuída a ela.

    Mesma função usando expressões de função:

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

    Isso ocorre porque durante a execução, parece que:

    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. Não é seguro escrever declarações de função em blocos que não sejam de função, como se, por não estarem acessíveis.

    if (test) {
        function x() { doSomething(); }
    }
    
  3. Expressão de função nomeada como a abaixo, pode não funcionar nos navegadores Internet Explorer antes da versão 9.

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

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 função.

Com

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

, esta definição de myfunction substituirá 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.


Em termos de custo de manutenção de código, as funções nomeadas são mais preferíveis:

  • Independente do lugar onde eles são declarados (mas ainda limitados pelo escopo).
  • Mais resistente a erros como inicialização condicional (você ainda pode substituir se quiser).
  • O código se torna mais legível ao alocar funções locais separadamente da funcionalidade do escopo. Geralmente, no escopo, a funcionalidade vai primeiro, seguida por declarações de funções locais.
  • Em um depurador, você verá claramente o nome da função na pilha de chamadas, em vez de uma função "anônima / avaliada".

Eu suspeito que mais PROS para funções nomeadas são seguir. E o que é listado como uma vantagem de funções nomeadas é uma desvantagem para as anônimas.

Historicamente, as funções anônimas surgiram da incapacidade do JavaScript como linguagem para listar membros com funções nomeadas:

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

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 :)

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


O primeiro (função doSomething (x)) deve fazer parte de uma notação de objeto.

O segundo ( var doSomething = function(x){ alert(x);}) é simplesmente criar uma função anônima e atribuí-la a uma variável doSomething,. Então doSomething () irá chamar a função.

Você pode querer saber o que é uma declaração de função e uma expressão de função .

Uma declaração de função define uma variável de função nomeada sem requerer atribuição de variável. As declarações de função ocorrem como construções independentes e não podem ser aninhadas em blocos que não sejam de função.

function foo() {
    return 3;
}

ECMA 5 (13.0) define a sintaxe como
função Identifier (FormalParameterList opt ) {FunctionBody}

Na condição acima, o nome da função é visível dentro de seu escopo e do escopo de seu pai (caso contrário, seria inacessível).

E em uma expressão de função

Uma expressão de função define uma função como parte de uma sintaxe de expressão maior (geralmente uma atribuição de variável). Funções definidas através de expressões de funções podem ser nomeadas ou anônimas. Expressões de função não devem começar com “função”.

// 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) define a sintaxe como
função Identifier opt (FormalParameterList opt ) {FunctionBody}


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 função e declarações de variáveis ​​são sempre movidas ( hoisted ) de forma invisível para o topo do seu escopo de contenção pelo intérprete JavaScript. Parâmetros de função 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 função, todo o corpo da função também será içado :

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

Eles são bem parecidos com algumas pequenas diferenças, primeiro um é uma variável que atribui a uma função anônima (Declaração de Função) e um segundo é o modo normal de criar uma função em JavaScript (Declaração de função Anônima), ambos têm uso, contras e pros. :

1. Expressão de Função

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

Uma Expressão de Função define uma função como parte de uma sintaxe de expressão maior (geralmente uma atribuição de variável). Funções definidas através de Funções Expressões podem ser nomeadas ou anônimas. Função Expressões não devem começar com “função” (daí os parênteses ao redor do exemplo auto-invocador abaixo).

Atribuir uma variável a uma função, significa não Hoisting, como sabemos que funções em JavaScript podem Hoist, significa que elas podem ser chamadas antes de serem declaradas, enquanto variáveis ​​precisam ser declaradas antes de obter acesso a elas, então significa que neste caso não podemos acessar a função antes de onde ela está declarada, também pode ser uma maneira de você escrever suas funções, para as funções que retornam outra função, esse tipo de declaração pode fazer sentido, também no ECMA6 & acima você pode atribuir isso a uma função de seta que pode ser usado para chamar funções anônimas, também esta maneira de declarar é uma maneira melhor de criar funções construtoras em JavaScript.

2. Declaração de Função

function functionTwo() {
    // Some code
}

Uma declaração de função define uma variável de função nomeada sem exigir atribuição de variável. Função Declarações ocorrem como construções independentes e não podem ser aninhadas dentro de blocos que não sejam de função. É útil pensar neles como irmãos de declarações de variáveis. Assim como as Declarações de Variáveis ​​devem começar com “var”, as Declarações de Função devem começar com “função”.

Esta é a maneira normal de chamar uma função em JavaScript, essa função pode ser chamada antes mesmo de você declarar como em JavaScript todas as funções são hasteadas, mas se você tiver 'use strict' isso não vai ser Hoisted como esperado, é uma boa maneira chamar todas as funções normais que não são grandes em linhas e nenhuma delas é uma função construtora.

Além disso, se você precisar de mais informações sobre como o içamento funciona em JavaScript, visite o link abaixo:

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


Sobre o desempenho:

Novas versões da V8introdução de várias otimizações sob o capô e assim o fizeram SpiderMonkey.

Quase não há diferença agora entre expressão e declaração.
A expressão de função parece ser mais rápida agora.

Chrome 62.0.3202

FireFox 55

Chrome Canary 63.0.3225


Anonymousexpressões de função parecem ter melhor desempenho em relação à Namedexpressão de função.


Firefox Chrome Canary Chrome


Ambas são formas diferentes de definir uma função. A diferença é como o navegador interpreta e carrega-os em um contexto de execução.

O primeiro caso é de expressões de função que são carregadas apenas quando o interpretador atinge essa linha de código. Então, se você fizer o seguinte, você receberá um erro que o functionOne não é uma função .

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

A razão é que na primeira linha nenhum valor é atribuído ao functionOne e, portanto, é indefinido. Estamos tentando chamá-lo como uma função e, portanto, estamos recebendo um erro.

Na segunda linha, estamos atribuindo a referência de uma função anônima ao functionOne.

O segundo caso é de declarações de função que são carregadas antes de qualquer código ser executado. Portanto, se você fizer o seguinte, não receberá nenhum erro, já que a declaração é carregada antes da execução do código.

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

No JavaScript, existem duas maneiras de criar funções:

  1. Declaração de função:

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

    Isso é muito básico, autoexplicativo, usado em muitos idiomas e padrão na família C de idiomas. Nós declaramos uma função definida e executamos chamando-a.

    O que você deve saber é que funções são objetos em JavaScript; internamente criamos um objeto para a função acima e lhe atribuímos um nome chamado fn ou a referência ao objeto é armazenada em fn. Funções são objetos em JavaScript; uma instância de função é, na verdade, uma instância de objeto.

  2. Expressão de função:

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

    JavaScript tem funções de primeira classe, ou seja, criar uma função e atribuí-la a uma variável, assim como você cria uma string ou um número e a atribui a uma variável. Aqui, a variável fn é atribuída a uma função. A razão para este conceito é funções são objetos em JavaScript; fn está apontando para a instância do objeto da função acima. Nós inicializamos uma função e a atribuímos a uma variável. Não está executando a função e atribuindo o resultado.

Referência: Sintaxe de declaração de função JavaScript: var fn = function () {} vs função fn () {}


À luz do argumento "funções nomeadas apresentadas em rastreios de pilha", os modernos mecanismos de JavaScript são realmente capazes de representar funções anônimas.

No momento em que escrevo, V8, SpiderMonkey, Chakra e Nitro sempre se referem a funções nomeadas por seus nomes. Eles quase sempre se referem a uma função anônima pelo seu identificador, se tiver um.

O SpiderMonkey pode descobrir o nome de uma função anônima retornada de outra função. O resto não pode.

Se você realmente quisesse que seus callbacks de sucesso e iterador aparecessem no rastreamento, você poderia nomear esses também ...

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

Mas na maior parte não vale a pena enfatizar.

Arnês ( 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 e.i (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

Macaco aranha

func.name: 
Trace:
[email protected]://localhost:8000/test.js:4:5
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: b
Trace:
[email protected]://localhost:8000/test.js:7:9
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: d
Trace:
[email protected]://localhost:8000/test.js:10:9
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: 
Trace:
[email protected]://localhost:8000/test.js:4:5
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: b
Trace:
[email protected]://localhost:8000/test.js:7:9
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: d
Trace:
[email protected]://localhost:8000/test.js:10:9
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: 
Trace:
[email protected]://localhost:8000/test.js:17:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: j
Trace:
[email protected]://localhost:8000/test.js:20:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: l
Trace:
[email protected]://localhost:8000/test.js:23:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: 
Trace:
m</<@http://localhost:8000/test.js:28:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: n
Trace:
[email protected]://localhost:8000/test.js:33:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: p
Trace:
[email protected]://localhost:8000/test.js:38:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1

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 e.i (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:
[email protected]://localhost:8000/test.js:4:22
http://localhost:8000/test.js:47:13
[email protected][native code]
global [email protected]://localhost:8000/test.js:44:33

func.name: b
Trace:
[email protected]://localhost:8000/test.js:7:26
http://localhost:8000/test.js:47:13
[email protected][native code]
global [email protected]://localhost:8000/test.js:44:33

func.name: d
Trace:
[email protected]://localhost:8000/test.js:10:26
http://localhost:8000/test.js:47:13
[email protected][native code]
global [email protected]://localhost:8000/test.js:44:33

func.name: 
Trace:
[email protected]://localhost:8000/test.js:4:22
http://localhost:8000/test.js:47:13
[email protected][native code]
global [email protected]://localhost:8000/test.js:44:33

func.name: b
Trace:
[email protected]://localhost:8000/test.js:7:26
http://localhost:8000/test.js:47:13
[email protected][native code]
global [email protected]://localhost:8000/test.js:44:33

func.name: d
Trace:
[email protected]://localhost:8000/test.js:10:26
http://localhost:8000/test.js:47:13
[email protected][native code]
global [email protected]://localhost:8000/test.js:44:33

func.name: 
Trace:
[email protected]://localhost:8000/test.js:17:30
http://localhost:8000/test.js:47:13
[email protected][native code]
global [email protected]://localhost:8000/test.js:44:33

func.name: j
Trace:
[email protected]://localhost:8000/test.js:20:30
http://localhost:8000/test.js:47:13
[email protected][native code]
global [email protected]://localhost:8000/test.js:44:33

func.name: l
Trace:
[email protected]://localhost:8000/test.js:23:30
http://localhost:8000/test.js:47:13
[email protected][native code]
global [email protected]://localhost:8000/test.js:44:33

func.name: 
Trace:
http://localhost:8000/test.js:28:30
http://localhost:8000/test.js:47:13
[email protected][native code]
global [email protected]://localhost:8000/test.js:44:33

func.name: n
Trace:
[email protected]://localhost:8000/test.js:33:30
http://localhost:8000/test.js:47:13
[email protected][native code]
global [email protected]://localhost:8000/test.js:44:33

func.name: p
Trace:
[email protected]://localhost:8000/test.js:38:30
http://localhost:8000/test.js:47:13
[email protected][native code]
global [email protected]://localhost:8000/test.js:44:33

Uma declaração de função e uma expressão de função atribuída a uma variável se comportam da mesma quando a ligação é estabelecida.

Há uma diferença, no entanto, em como e quando o objeto de função está realmente associado à sua variável. Essa diferença é devido ao mecanismo chamado de içamento variável em JavaScript.

Basicamente, todas as declarações de função e declarações de variáveis ​​são hasteadas no topo da função na qual a declaração ocorre (é por isso que dizemos que o JavaScript tem escopo de função ).

  • Quando uma declaração de função é hasteada, o corpo da função "segue", de modo que quando o corpo da função é avaliado, a variável será imediatamente ligada a um objeto de função.

  • Quando uma declaração de variável é hasteada, a inicialização não segue, mas é "deixada para trás". A variável é inicializada para undefinedno início do corpo da função, e será atribuído um valor em sua posição original no código. (Na verdade, será atribuído um valor a cada local onde ocorre uma declaração de uma variável com o mesmo nome.)

A ordem de içamento também é importante: as declarações de função têm precedência sobre as declarações de variáveis ​​com o mesmo nome, e a última declaração de função tem precedência sobre as declarações de função anteriores com o mesmo nome.

Alguns exemplos...

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

A variável fooé içada para o topo da função, inicializada para undefined, de modo que !fooé true, portanto, foodesignada 10. O escopo foode fora barnão desempenha nenhum papel e é intocado.

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

As declarações de função têm precedência sobre as declarações de variáveis ​​e a última declaração de função "adere".

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

Neste exemplo aé inicializado com o objeto de função resultante da avaliação da segunda declaração de função e, em seguida, é atribuído 4.

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

Aqui, a declaração da função é hasteada primeiro, declarando e inicializando a variável a. Em seguida, essa variável é atribuída 10. Em outras palavras: a atribuição não atribui à variável externa a.


Há três comparações dignas de nota entre as duas declarações diferentes de funções, conforme listado abaixo.

  1. Disponibilidade (escopo) da função

O seguinte funciona porque function add()está com o escopo definido para o bloco mais próximo:

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

function add(a, b){
  return a + b;
}

O seguinte não funciona (porque o var add=superseeds o function add()).

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

var add=function add(a, b){
  return a + b;
}

O seguinte não funciona porque addé declarado depois de ser usado.

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

var add=function(a, b){
  return a + b;
}

  1. (função) .name

O nome de uma função function thefuncname(){}é thefuncname quando é declarado dessa maneira.

function foobar(a, b){}

console.log(foobar.name);

var a = function foobar(){};

console.log(a.name);

Caso contrário, se uma função é declarada como function(){}, a função .name é a primeira variável usada para armazenar a função.

var a = function(){};
var b = (function(){ return function(){} });

console.log(a.name);
console.log(b.name);

Se não houver variáveis ​​configuradas para a função, o nome da função será a string vazia ( "").

console.log((function(){}).name === "");

Por fim, enquanto a variável à qual a função é atribuída inicialmente define o nome, as variáveis ​​sucessivas configuradas para a função não alteram o nome.

var a = function(){};
var b = a;
var c = b;

console.log(a.name);
console.log(b.name);
console.log(c.name);

  1. atuação

No V8 do Google e no Spidermonkey do Firefox, pode haver uma diferença de compilação JIS de microssegundos, mas no final o resultado é exatamente o mesmo. Para provar isso, vamos examinar a eficiência do JSPerf em microbenchmarks comparando a velocidade de dois trechos de código em branco. Os testes JSPerf são encontrados aqui . E os testes jsben.ch são encontrados aqui . Como você pode ver, há uma diferença notável quando não deveria haver nenhuma. Se você é realmente um fanático por desempenho como eu, então talvez valha a pena tentar reduzir o número de variáveis ​​e funções no escopo e, especialmente, eliminar o polimorfismo (como usar a mesma variável para armazenar dois tipos diferentes).

Qual é o "bloco mais próximo"

O "bloco mais próximo" é a "função" mais próxima (incluindo funções assíncronas, funções geradoras e funções geradoras assíncronas). No entanto, curiosamente, um function functionName() {}comporta - se como um var functionName = function() {}quando em um bloco sem fechamento para itens fora do referido fechamento. Observar.

  • Normal var add=function(){}

try {
  // typeof will simply return "undefined" if the variable does not exist
  if (typeof add !== "undefined") {
    add(1, 1); // just to prove it
    console.log("Not a block");
  }else if(add===undefined){ // this throws an exception if add doesn't exist
    console.log('Behaves like var add=function(a,b){return a+b}');
  }
} catch(e) {
  console.log("Is a block");
}
var add=function(a, b){return a + b}

  • Normal function add(){}

try {
  // typeof will simply return "undefined" if the variable does not exist
  if (typeof add !== "undefined") {
    add(1, 1); // just to prove it
    console.log("Not a block");
  }else if(add===undefined){ // this throws an exception if add doesn't exist
    console.log('Behaves like var add=function(a,b){return a+b}')
  }
} catch(e) {
  console.log("Is a block");
}
function add(a, b){
  return a + b;
}

  • Função

try {
  // typeof will simply return "undefined" if the variable does not exist
  if (typeof add !== "undefined") {
    add(1, 1); // just to prove it
    console.log("Not a block");
  }else if(add===undefined){ // this throws an exception if add doesn't exist
    console.log('Behaves like var add=function(a,b){return a+b}')
  }
} catch(e) {
  console.log("Is a block");
}
(function () {
    function add(a, b){
      return a + b;
    }
})();

  • Declaração (tais como if, else, for, while, try/ catch/ finally, switch, do/ while, with)

try {
  // typeof will simply return "undefined" if the variable does not exist
  if (typeof add !== "undefined") {
    add(1, 1); // just to prove it
    console.log("Not a block");
  }else if(add===undefined){ // this throws an exception if add doesn't exist
    console.log('Behaves like var add=function(a,b){return a+b}')
  }
} catch(e) {
  console.log("Is a block");
}
{
    function add(a, b){
      return a + b;
    }
}

  • Função de seta com var add=function()

try {
  // typeof will simply return "undefined" if the variable does not exist
  if (typeof add !== "undefined") {
    add(1, 1); // just to prove it
    console.log("Not a block");
  }else if(add===undefined){ // this throws an exception if add doesn't exist
    console.log('Behaves like var add=function(a,b){return a+b}')
  }
} catch(e) {
  console.log("Is a block");
}
(() => {
    var add=function(a, b){
      return a + b;
    }
})();

  • Função de seta com function add()

try {
  // typeof will simply return "undefined" if the variable does not exist
  if (typeof add !== "undefined") {
    add(1, 1); // just to prove it
    console.log("Not a block");
  }else if(add===undefined){ // this throws an exception if add doesn't exist
    console.log('Behaves like var add=function(a,b){return a+b}')
  }
} catch(e) {
  console.log("Is a block");
}
(() => {
    function add(a, b){
      return a + b;
    }
})();


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 objeto.

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.)


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 função só pode ser chamada após esse ponto no código.

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

Isso ocorre porque, com a primeira variante, a função é atribuída à variável foo no tempo de execução. No segundo, a função é 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 função . Isso envolve usar o operador "function" para criar uma função - o resultado desse operador pode ser armazenado em qualquer variável ou propriedade de objeto. A expressão de função é poderosa dessa maneira. A expressão de função é freqüentemente chamada de "função anônima", porque não precisa ter um nome,
  2. Seu segundo exemplo é uma declaração de função . Isso usa a instrução "function" para criar uma função. A função é 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 objeto posteriormente.
  3. A terceira maneira de definir uma função é 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 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?


Outra diferença que não é mencionada nas outras respostas é que se você usar a função anônima

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

e usar isso como um construtor como em

var one = new functionOne();

então one.constructor.namenão será definido. Function.namenão é padrão, mas é suportado pelo Firefox, Chrome, outros navegadores derivados do Webkit e pelo IE 9+.

Com

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

é possível recuperar o nome do construtor como uma string com two.constructor.name.


A Resposta de Greg é boa o suficiente, mas eu ainda gostaria de acrescentar algo a isso que eu aprendi apenas agora assistindo aos vídeos de Douglas Crockford .

Expressão de função:

var foo = function foo() {};

Declaração de função:

function foo() {};

A declaração da função é apenas um atalho para a varinstrução com um functionvalor.

assim

function foo() {};

se expande para

var foo = function foo() {};

Que se expande ainda mais para:

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

E ambos são içados para o topo do código.


Se você está no escopo global, não há muita diferença. Leia Kangax's resposta Kangax's para explicação

Se você estiver em uma função, então var criará uma variável local, "no var" procurará a cadeia de escopo até encontrar a variável ou atingir o escopo global (no ponto em que será criada):

// These are both globals
var foo = 1;
bar = 2;

function()
{
    var foo = 1; // Local
    bar = 2;     // Global

    // Execute an anonymous function
    (function()
    {
        var wibble = 1; // Local
        foo = 2; // Inherits from scope above (creating a closure)
        moo = 3; // Global
    }())
}

Se você não está fazendo uma tarefa, então você precisa usar var :

var x; // Declare x




javascript function syntax idioms