What is the difference between the functions var name = function () and function name ()?

128

I see in some codes different ways of defining a function, but I do not know the difference if it exists. What is the difference between these functions?

Function 1

function teste(valor){
    return (valor > 1) ? true : false;
}

Function 2

var teste = function(valor){
    return (valor > 1) ? true : false;
}
    
asked by anonymous 18.04.2014 / 00:35

4 answers

99

Function statement: function name ()

A function declaration defines a function variable without the need for variable assignment. They are constructs , and can not be nested in non-function blocks (see comment below). It would be like a "relative" of variable declarations. Just as variables need to be declared with var , functions are declared with function .

function bar() {
   return 3;
}

bar() //3
bar  //function


Function expression: var name = function ()

A function expression defines a function as part of a larger syntax expression, usually a variable assignment. Functions defined with function expressions may be named or anonymous. They can not start with function , so the parentheses are used in the "auto invocation" in the example below:

//expressão anônima de função
var a = function() {
   return 3;
}

//expressão nominada de função
var a = function bar() {
   return 3;
}

//expressão "autoinvocada" de função
(function digaOi() {
    alert("Oi!");
})();


Scope visibility example:

<script>
  funcaoUm(); // Da erro, ainda nao foi definida
  var funcaoUm = function() { }
</script>

<script>
  var funcaoDois = function banana() {
    banana(); // Nao da erro, está no escopo
  }
  banana(); // Da erro, está fora do escopo (exceto no IE)
</script>

<script>
  funcaoTres(); // Nao da erro, é resolvida ao compilar
  function funcaoTres() { }
</script>


"Functions can not be declared in non-code blocks"

Let's look at this code:

if (true) {
  function foo() {
    return 'primeiro';
  }
} else {
  function foo() {
    return 'segundo';
  }
}
foo();

Some browsers will return "first", others "second"!

According to the specification, function declarations may even appear within function blocks, but not within if , while , for , and other structural blocks.

In these cases, what should happen is a syntax error , but virtually none of the implementations do this in practice, and what is worse, each treats codes like the example in a different way (with the exception of BESEB and DMDScripot, as this font ).


Source: Function Declarations vs. Function Expressions , SOen , kangax

    
18.04.2014 / 00:39
51
  

If you're in a hurry, it's best to see examples of scope visibility in Bacco's response:)

The main difference is of scope visibility, which Bacco has demonstrated in response from him examples. To understand how this works, you need to understand how it works what is called variable hoisting in JavaScript. If you think variables and functions are created at the point of the code they are declared in, you are wrong.

First of all, a brief consideration of how JavaScript works: there is a global scope, and there are function scopes. Each function creates a new scope. If there are nested functions, the inner ones see the variables of the outer ones, but not the other. The mgibsonbr answer about closures illustrates this well:

function x(a1) {          // "x" tem acesso a "a"
    var a2;
    function y(b1) {      // "y" tem acesso a "a" e "b"
        var b2;
        function z(c1) {  // "z" tem acesso a "a", "b", e "c"
            var c2;

Each time a function is invoked, a execution context is created for it, where the variables it defines are stored. In the case of the x function above, the execution context contains references to a1 , a2 and y (respectively, a parameter, a variable, and a function). Now, consider the following example:

function x(a) {
    var a = "foo";
    function a() {
        // nada
    }
    alert(typeof a);
}
x(10);

What will happen on the alert? The type "number" of the argument passed, the type "string" of the variable, or the type "function" of the function? Answer: "string" ( test yourself ). At this time, you scratch your head and say:

  

But how come ?! The function was declared after of the variable! You should give "function"!

Yes, it makes sense what you thought. It turns out that the algorithm responsible for the binding of the arguments, variables, and functions to the execution context does this in a very specific order, which is as follows:

  • Arguments
  • Function statements
  • Variables
  • If there are equal names between arguments, function declarations, and variables, they will be overwritten in that order. In our example, a starts as the number 10 , then it is overwritten by the function, and finally it is overwritten by the variable (before the assignment). This all happens before any code is executed in the function, including assigning the value "foo" to a . In code, what happens is something like this:

    function x(a) {
        function a() {
            // nada
        }
        var a; // undefined, por enquanto
        a = "foo";
        alert(typeof a); // "string"
    }
    x(10);
    

    Notice that the variable declaration is separate from the assignment. It is said that the statement is "raised" or "hoisted" ( hoisted ) to the top of the scope. See this example:

    function f() {
        var a = 10;
        var b = 10;
        function c() {}
        var d = function() {};
    }
    

    This is actually interpreted like this:

    function f() {
        function c() {}
        var a = undefined, b = undefined, d = undefined;
        a = 10;
        b = 10;
        d = function() {};
    }
    

    Look at that thing! The c function is available from the beginning, but function d is not! This is because c was created via function declaration , while the function in d was created via function expression (declarations always have names, and always start with function as the first thing on the line, disregarding the spaces). If we want to invoke c before the line where it is declared, no problem, since hoisting makes it already available:

    function f() {
        var a = 10;
        var b = 10;
        c(); // SEM PROBLEMAS!
        function c() {}
        var d = function() {};
    }
    

    The same is not true for d : there will only be a function in d after the line where the assignment is made. See:

    function f() {
        var a = 10;
        var b = 10;
        d(); // TypeError! Estamos tentando chamar undefined como função
        function c() {}
        var d = function() {};
    }
    

    Therefore, answering the question: var name = function() and function name() are different because the first is a variable declaration, which is assigned a function, while the second is a function declaration. This has consequences as to when the function will be available to be invoked.

        
    02.10.2014 / 22:11
    26

    Despite Bacco's fairly complete explanation, it's worth pointing out one thing about function expressions.

    When you store an anonymous inline function in a variable, the variable identifier does not become the function name. The function remains anonymous, it can only be accessed through a variable (which has a name). You can easily check this by looking at the name property of the function:

    var foo = function(){}
    console.log(foo.name); //Não mostra nada
    var bar = function baz(){}
    console.log(bar.name) //Mostra "baz"
    

    It is relevant to know this for clearer error messages. If an error occurs when you call an anonymous function, the stack will only show "anonymous function". If the error occurs in an inline function that has a name, the name of the function will appear.

    As pointed out by the bfavaretto , the name property is the way to access the function name externally, but the name is also available within the function itself, which allows inline functions to be recursive¹. Home To get the same recursive behavior of anonymous functions, you should use arguments.callee , which MUST be avoided because This property is deprecated and does not work in strict mode .

    ¹ - Old versions of IE leak this variable out of scope, cf. kangax.github.io/nfe

        
    02.10.2014 / 21:12
    7

    There are many differences, one of them is hoisting , function has priority in the interpreter.

    foo(); foo = function() {}
    //saída: Uncaught ReferenceError: foo is not defined (foo não está definido)
    
    bar(); function bar() {}
    //saída: undefined (indefinido)
    
        
    01.07.2017 / 11:15