Javascript functions like "var foo = function bar() ..."?

Solution 1:

You are seeing a named function expression (NFE).

An anonymous function expression is where you assign a function without a name to a variable1:

var add = function () {
  console.log("I have no own name.");
}

A named function expression is where you assign a named function to a variable (surprise!):

var add = function addNums() {
  console.log("My name is addNums, but only I will know.");
}

The function's name is only available within the function itself. This enables you to use recursion without necessarily knowing the "outside name" of the function - even without having to set one in the first place (think callback functions).

The name you choose shadows an existing name, so if another addNums is defined elsewhere it will not be overridden. This means you can use any name you like without fear for scoping problems or breaking anything.

In the past you would have used arguments.callee to refer to a function inside itself without knowing its name. But support for that is being removed from JavaScript2, so NFEs are the correct way to do this nowadays.

Here is a lot of stuff to read on the topic: http://kangax.github.io/nfe/


1 Assigning it to a variable is not necessary, it just serves as an example to distinguish it from a plain function declaration. It could be any other context where JS expects an expression (a function argument, for example).

2 You will receive an error if you have strict mode in effect and try to use arguments.callee.

Solution 2:

The problem

You are using a named function expression - and a function expression's name is not available outside of that function's scope:

// Function statement
function statement() {
    console.log("statement is a type of " + typeof statement);
}
statement();
console.log("statement is a type of " + typeof statement);

results in:

statement is a type of function
statement is a type of function

whereas:

// Function expression with a name
var expression = function namedExpression() {
    console.log("namedExpression is a type of " + typeof namedExpression);
};

expression();
// namedExpression();  // uncommenting this will cause an exception
console.log("expression is a type of " + typeof expression);
console.log("namedExpression is a type of " + typeof namedExpression);

will produce:

namedExpression is a type of function
expression is a type of function
namedExpression is a type of undefined

The solution

Depending on what you are trying to do, you want do do one of the following:

  • Change your function declaration to use a statement and then alias your function:

    function addNums(a, b) {
        return a + b;
    }
    
    var add = addNums;
    
  • Alias both names to your expression:

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

Why does JavaScript do things this way?

Named function expressions are useful because they let you reference a function inside itself and they give you a name to look at in a debugger. However, when you use a function as a value you don't generally want parts of it leaking into the enclosing scope. Consider:

(function setup() {
    var config = retrieveInPageConfig();
    if (config.someSetting) {
        performSomeOtherSetup();
    }
    kickOffApplication();
})();

This is a perfectly licit use of a function expression - in such a case you would not expect the name setup to leak into the enclosing scope. Assigning a named function expression to a variable is just a special case of this, that just happens to look like a function statement declaration.

Solution 3:

addNums is only available in the scope of the newly-defined function.

Quite obviously, when a function expression has a name (technically — Identifier), it is called a named function expression. What you’ve seen in the very first example — var bar = function foo(){}; — was exactly that — a named function expression with foo being a function name. An important detail to remember is that this name is only available in the scope of a newly-defined function; specs mandate that an identifier should not be available to an enclosing scope.

Read more detail form this article.

Solution 4:

You should either declare as named function:

function addNums(){

}

or assign function to the variable:

var add= function(){// your code }

The reason why addNum() doesn't return anything is because it's not added to the global scope with the way you declare it.