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

Asked

Viewed 6,116 times

148

I see in some codes different ways to define a function, but I don’t 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;
}
  • 23

    whenever you have comparisons like a > b, a <= b, etc the result of the comparison is already true or false :)

  • 2

    Function 1 is defined when the script is parsed(parse time) and function 2 when it is executed(run-time)

5 answers

116


Function Statement: Function name()

A function statement defines a function variable without the need for variable assignment. They are constructs independent, and cannot be nested in non-function blocks (see comment below). It would be like a "relative" of variable statements. 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 syntactic expression, usually a variable assignment. Functions defined with function expressions may have a name or be anonymous. They cannot 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!");
})();


Example of scope visibility:

<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 cannot 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 statements can even appear within function blocks, but not within function blocks if, while, for and other structural blocks.

In these cases, what should occur is a syntax error, but virtually none of the implementations do this in practice, and what’s worse, each treats code like the example in a different way (with the exception of BESEB and Dmdscripot, according to this source).


Sources: Function Declarations vs. Function Expressions, Soen, kangax

  • 12

    It is worth pointing out that the main practical difference is the visibility of the scope, demonstrated in the last example.

  • 1

    Bacco, could you put a more realistic example of the differences in practice? Other, what is the difference in the practice of var a = function() and var a = function bar()?

  • 1

    @Carloscinelli the problem is that in practice, for the user who uses only the basic, does not give almost any difference even. The biggest difference you notice in the scope. As for the var a = function bar(), I added in the example.

  • I don’t understand the phrase "cannot be nested in non-function blocks". Scroll to put an example of this in Statement (cannot) and Expression (can)?

  • Okay, I think I’m gonna open up a reward to stimulate more answers.

  • 2
  • 2

    @Brasofilo as requested, we have example of the issue of blocks ;)

Show 2 more comments

58

If you are in a hurry, better see examples scope visibility in Bacco’s response :)

The main difference is of scope visibility, which Bacco demonstrated in the examples of his answer. To understand how this works, you need to understand how what is called variable Hoisting in Javascript. If you think that variables and functions are created at the point in the code in which they are declared, you are wrong.

First of all, a brief consideration of the functioning of the scope in Javascript: there is the global scope, and there are the function scopes. Each function creates a new scope. If there are nested functions, the innermost ones see the variables of the outermost ones, but not the other way around. A mgibsonbr’s response to 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 to it, where the variables it defines are stored. In the case of the function x 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 come out in the Alert? The guy "number" of the past argument, the type "string" of the variable, or the type "function" function? Answer: "string" (test yourself). At this point, you scratch your head and say,:

But how so?! The function has been declared afterward variable! Should give "Function"!

Yeah, it makes sense what you thought. Turns out the algorithm responsible for Binding of the arguments, variables and functions to the execution context does so in a very specific order, which is the following:

  1. Arguments
  2. Job statements
  3. Variables

If there are equal names between arguments, function statements and variables, they will be superscripted following this order. In our example, a begins 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 the assignment of 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);

Note that the variable declaration is separated from the assignment. It is said that the statement is "erected" 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() {};
}

It’s actually interpreted that way:

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

Look at that thing! The function c is available from the start, but the d function is not! That’s because c was created via function statement, while the function in d was created via function expression (statements always have a name, 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, there is no problem, since the 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 be only one 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() {};
}

So, to answer the question: var name = function() and function name() are different because the first is a variable statement, to which a function is assigned, while the second is a function statement. This has consequences in relation to when the function will be available to be invoked.

  • 5

    +1 I even knew that the Hoisting existed but did not know this level of detail! And by my tests, the thing is even more confusing than it seems: if you declare var x; (without attribution) to function x() { }, the var x has no effect (i.e. it does not receive undefined at no time). Example. (Note: according to the linked specification - item 8.c - your example is yes correct, I’m not questioning that; I just gave one another example where the "interpretation" is slightly different from its)

  • 1

    I omitted this "detail" because it was already getting too complicated :) If you look at step 8 of algorithm, will see that when trying to create the variables it does nothing if there is already a Binding for the identifier (the if step (c) does not have else).

  • +1, great reply @bfavaretto, our did not know this order of Binding, of javascript, the full clarification of these details can cause that we do not get into "illogical" errors, as the change of the statement order by the interpreter. (If this happens to me until yesterday, would think the browser or javascript were bugged. = D)

  • @bfavaretto, then as you demonstrated in the examples, to variables declared with the keyword var are 'hoisted', even before the functions? since both var and function possess Hoisting.

  • So @felipecardozo, the functions are hoisted before the variables - which means that if a variable and a function have the same name, the variable overwrites the function.

  • So it is worth always creating functions with the word Function before to be called from anywhere?

Show 1 more comment

33

Despite the fairly complete explanation of Bacco, it is 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 property name of 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 to get clearer error messages. If an error occurs when you call an anonymous function, the stack will show only "Anonymous Function". If the error occurs in a named inline function, its name will appear.

As pointed out by bfavaretto, the property name 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¹.
To get the same recursive behavior of anonymous functions, you must use arguments.callee, which MUST be avoided as this property is deprecated and does not work in Strict mode.

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

  • 3

    Really, this is important. Note that in the case of named function expressions, this name is available in two ways: 1) outside the function, via fnObj.name, as you showed; 2) within the function, directly by name, allowing recursive calling (but older versions of IE leak this variable out of scope, cf. http://kangax.github.io/nfe/).

11

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

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

bar(); function bar() {}
//saída: undefined (indefinido)

-1

the first is a pure function and you recover only the.ex function: Function(value){ Return (value > 1) ? true : false; }

Document.write(Function())

and the 2nd function is within a variable, so you can recover the variable and not the.ex function: var test = Function(value){ Return (value > 1) ? true : false; } Document.write(test)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.