5

I was told that you must always declare functions in JavaScript. Is that true? What is the advantage of it?

I usually assign functions to a variable as such:

var foo = function() {};

But supposedly this is wrong, something to do stack tracing. Can someone please explain? I was told to do:

var foo = function fooBar() {};

Would it make sense if it's assigned to an object?

var Foo = {};
Foo.Bar = function Bar() {};

Mind you these functions are not inside of the global scope nor self-executed nor used multiple times.

7
  • 4
    possible duplicate of var functionName = function() {} vs function functionName() {} Commented Apr 1, 2015 at 21:20
  • 1
    Seems like your question is about assigning functions a name. Yes, that helps with stack tracing so you don't see merely a bunch of 'anonymous function' entries. Commented Apr 1, 2015 at 21:21
  • @MikeRobinson that questions is more about hoisting. I know the difference between those two functions. Please re-read the question. Commented Apr 1, 2015 at 21:23
  • @JAL can you please elaborate? Commented Apr 1, 2015 at 21:23
  • 1
    Be wary: if you need to support <= IE8, named function expressions can cause a whole lot of headache. It's been well documented, but this is a good summary: kangax.github.io/nfe/#jscript-bugs Commented Apr 1, 2015 at 21:48

1 Answer 1

3

First of all, a small note on terminology: what you have isn’t a function declaration. This is a function declaration:

function fooBar() {
}

It creates a function named fooBar accessible through the variable fooBar. This is an assignment involving a named function expression:

var foo = function fooBar() {
};

The function’s name is still fooBar, but the function is only bound to a fooBar variable inside the function itself and not outside. The fact that it does make the function accessible inside its scope without needing to refer to a variable in an outer scope, though, means that there are two reasons to name it:

  • For the ability to refer to the function inside itself regardless of code in the outer function!

    This can return whatever the outer function wants:

    function fooBar() {
        return fooBar.toString();
    }
    
    var baz = fooBar;
    fooBar = 5;
    baz(); // "5"
    

    This is always consistent:

    var fooBar = function fooBar() {
        return fooBar.toString();
    };
    
    var baz = fooBar;
    fooBar = 5;
    baz(); // "function fooBar() { …"
    
  • And yes, for a more detailed stack trace:

    function trace(func) {
        try {
            func();
        } catch (error) {
            console.log(error.stack);
        }
    }
    
    trace(function () {
        throw new Error("Bad thing");
    });
    /*
    Error: Bad thing
        at /home/ryan/test.js:10:18
        at trace (/home/ryan/test.js:3:16)
        at Object.<anonymous> (/home/ryan/test.js:9:8)
        at Module._compile (module.js:410:26)
        at Object.Module._extensions..js (module.js:428:10)
        at Module.load (module.js:335:32)
        at Function.Module._load (module.js:290:12)
        at Function.Module.runMain (module.js:451:10)
        at startup (node.js:123:18)
        at node.js:866:3
    */
    
    trace(function descriptiveName() {
        throw new Error("Bad thing");
    });
    /*
    Error: Bad thing
        at descriptiveName (/home/ryan/test.js:14:18)
        at trace (/home/ryan/test.js:3:16)
        at Object.<anonymous> (/home/ryan/test.js:13:8)
        at Module._compile (module.js:410:26)
        at Object.Module._extensions..js (module.js:428:10)
        at Module.load (module.js:335:32)
        at Function.Module._load (module.js:290:12)
        at Function.Module.runMain (module.js:451:10)
        at startup (node.js:123:18)
        at node.js:866:3
    */
    

    (Node.js pictured here.) Note the descriptiveName at the top of the second stack trace. This is especially convenient when you have slightly complicated systems of asynchronous callbacks, events, methods on objects that are passed around, and so on.

Sign up to request clarification or add additional context in comments.

1 Comment

You could perhaps also name IIFE to describe what a code block does. E.g. (function applyFixIfNeeded() { //fix in here }()); rather than using comments likes //This applies a fix with code below. I actually prefer declaring functions at the bottom and invoke them at the top for this, but I've used that form in the past.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.