Are function expressions anonymous functions?

With the trend of using function expressions to declare functions, does this mean that the state of JavaScript has moved to be where we are programming using almost exclusively anonymous functions?

We are used to the idea of anonymous functions as being like the ones passed to the forEach method of arrays:

array.forEach(function () {
    // an anonymous function
});

However, when we assign a function to a variable, we are also creating an anonymous function:

var someFunc = function () {
    // this is an anonymous function too
};

And of course, with more structured techniques we frequently use anonymous functions too:

var project = (function () {
    // an anonymous function, normally acceptable
    ...
    return {
        init: function () {
            // yet more anonymous functions
            ...
        },
        ...
     };
}());

We can deal with that by naming the functions, but then we end up duplicating the function’s name:

var someFunc = function someFunc() {
  // now a named function
};

The above tends to look somewhat excessive due to the duplication of the function name, which prevents some from using it as a common programming technique.

We can always use function declarations, but they are being denigrated these days because people don’t like to deal with hoisting issues:

function someFunc() {
    // a function declaration
}

Are there problems with this trend of using anonymous functions? It can certainly make debugging more difficult because you no longer have access to the name of the functions that are involved.

Are there any other issues with anonymous functions? Or is it just something that we have to learn to live with now that we are programming with function expressions?

2 Likes

Modern browsers solve this by allowing you to name your function expressions - as you showed - just as long as you don’t expect the code to work in antiquated browsers such as IE8 that don’t support named expressions.

Note that the name you specify for internal debugging use need not be the same as the name of the variable you are assigning the function to.

var someFunc = function anotherFunc() {
  // now a named function so debugging can reference it as anotherFunc
};

someFunc();
1 Like

That’s a solid point. If we name the function expression – which we should, and there are linting rules to ensure we do – then assigning that function to a variable is redundant to leaving it as a declaration.

1 Like

No it isn’t.

  1. That overlooks hoisting.
  2. It breaks if the assignment is inside an if statement or other conditional code.

The hoisting of functions is only a problem if we expect variables to be undefined before a function is assigned to them. Normally such behaviour is best to be avoided.

Do function declarations break when they are changed from within conditional code?

In our recent discussions on this same topic, I mentioned that I rely on linters, and my views and opinions are predicated on that. If our code is checked by a linter, then there are no hoisting issues regardless if it’s a function expression or declaration.

If we were to hypothetically assume we didn’t have linters to catch issues like that, then my opinions might change, but we do have linters, and we ought to be using them all the time.

You’re right. If we want to create a function in a condition or loop, then it can’t be a declaration (though ES6 changes that a bit).

Function declarations inside a conditional or loop doesn’t play nice with hoisting and function scope. Imagine…

if (/* something */) {
    function f() { return 'f'; }
} else {
    function f() { return 'f2'; }
}

But since declarations are hoisted within their function scope, they could conceivably be interpreted this way:

// functions hoisted to top
function f() { return 'f'; }
function f() { return 'f2'; }

if (/* something */) {
} else {
}

But actually the correct interpretation here (according to ECMA, anyway) is a syntax error. In ES5, function declarations weren’t allowed in block statements like that because they’d have to be evaluated in nonsensical ways.

In ES6, function declarations are allowed in blocks and have block scope.

No, that’s not what I was asking. I’m talking about reassigning existing function declarations.

The function declaration is outside the conditional code, and another function is assigned to it from within the conditional code.

For example:

function foo() {
}
if (...) {
    foo = function bar() {
    };
}

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.