Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why always declare functions in JavaScript?

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.

like image 219
DevNoob Avatar asked Oct 19 '22 15:10

DevNoob


1 Answers

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.

like image 193
Ry- Avatar answered Oct 28 '22 22:10

Ry-