with Imagination: by Dustin Diaz

./with Imagination

A JavaScript, CSS, XHTML web log focusing on usability and accessibility by Dustin Diaz

JavaScript function declaration ambiguity

Thursday, February 22nd, 2007

Now say the title of this post ten times in a row, five times as fast… yea, anyway. This is meant to be a short and sweet tip about how you declare your functions in JavaScript; mainly because there is a little white lie floating out there that says that the two declarations are synonymous. But one is just shorthand for the other. Here they are represented in code:

two supposed synonymous declarations

// regular declaration
function foo() {
    // body...
};
// shorthand
var foo = function() {
    // body...
};

In reality, nothing is actually wrong with using either style, and they both work. However, there is one very basic situation where the shorthand style won’t yield the result you’re looking for, and the reason is fairly obvious and simple. Only the first one is an actual function declaration, whereas the shorthand method is just a regular variable declaration with an anonymous function assigned to it as its value. Here is the most basic scenario:

variable defining

var foo = 'bar';
alert(foo); // alerts 'bar'

alert(baz); // alerts 'undefined'
var baz = 'thunk';

The results of this scenario is trivial, but it proves the point. The second alert shows ‘undefined’ because the variable hasn’t been defined yet. Well, the same goes with functions when you’re assigning them to a variable. You can’t use them, until you’ve defined them (if you’re using shorthand). But with regular function declarations, the JavaScript interpreter knows to fetch the functions when it needs them, even if they aren’t declared until further parts in your code. Again, here is a basic scenario;

declaring functions before and after

sayHello(); // alerts 'Hello World'
function sayHello(){
    alert('Hello World');
};

sayGoodbye(); // throws error. sayGoodbye is not a function
var sayGoodbye = function() {
    alert('Goodbye World');
};

Lesson learned?

Just use regular function declarations all the time? Well, ok, I guess. The obvious use of using variable declaration is that you are indeed assigning ’something’ to a variable, and a key takeaway is that you can immediately self-invoke the anonymous function and return a different value back to it. This technique as I’ve discussed several times on this blog already is known as the modular format which is most commonly used for information hiding. As to why that’s important, you’ll hear why when my book gets published.

16 Responses to “JavaScript function declaration ambiguity”

  1. Mark Wubben

    One other downside of the anonymous functions is that they don’t have a name in a JavaScript debugger. And if you’d like to do {foo: function foo() { } }, you’ll find it throws a Syntax Error in Safari.

  2. Carlton Dickson

    Thanks for this article, I need to read the modular format article again though.
    Interesting to know you’ve got a book on the way, must have missed that point in your other posts, looking forward to it.

    Any idea of the proposed release date?

  3. Binny V A

    Does the var keyword hold any significance when used with functions?

  4. Jason Beaird

    Thanks Dustin, that was informative. I could always use more “best practices” types of js tips. Otherwise I tend to just do whatever works.

  5. Dustin Diaz

    Mark, you are so correct. I knew I was leaving that out (the fact that functions don’t have names), but didn’t want to adding more weight to the “brief tip.” That’s pretty bogus too that the snippet you wrote throws an error. Does that mean this would throw an error too?

    var foo = function foo() {
        // body...
    };
    var foo = (function foo() {
        // body...
    })();

    I suppose in the second example, you wouldn’t get the benefit of having a function name anyway, so that’s almost pointless. Anyway, thanks for pointing that out.

    Carlton, we’re shooting for this year to have the book released.

    Binny, it’s just a different way of doing things, and could keep your code looking more uniform if you feel style is important to you.

    Jason, glad you found it useful. Now it’s time to go buy your book!! :o

  6. Andrea Giammarchi

    In reality, nothing is actually wrong with using either style, and they both work.

    It’s not always true, if You declare a function using var some version of Internet Explorer has memory limits (function simply doesn’t work if it’s too much big).

    A function, in my opinion, should be declared always using regular style; after that You can use a reference variable, if You need them, without problems.

  7. Nicholas C. Zakas

    Another point about creating a function via variable assignment is to be careful of the scope in which it’s created. For example:

    function doSomething()
        var f = function () { .... };
        f2 = function () {...};
    }

    In this case, the function f exists only locally because of the use of var whereas f2 is available globally because var is omitted.

    Glad to see you’re back blogging again. Hope the new gig is working out well for you.

  8. Mark Wubben

    Dustin, those declarations are fine. I believe Safari is following the specification to the letter by throwing the syntax error, while Firefox, IE and Opera are less restrictive. It’s been a while since I looked through the spec though.

  9. Seb Frost

    Stupid question, but why do you call it shorthand when it’s clearly more to write?

  10. Johan Sundström

    Also worth knowing is that the var syntax is allowed in some places where a function declaration is not — inside a function, the spec only allows function declarations at the top of the function, whereas you may declare a var keyword later on, mid-function. Most, but not all, browsers handle both, in practice, though.

  11. H5N1

    It’s a well known (I think) matter.
    So if I declare

    
    var func= function(){
    /*some code here
    }
    

    and

    
    funtion func(){
    /*different code here
    }
    

    I could have different results using them because “func()” and “func” are two separate and different entities, but ambiguous ones.
    I guess the result is the important thing!
    Right? ;)

  12. justin

    Funny, I just prefer to not call my functions until after I’ve defined them.

  13. Instruct Me

    I have several different web pages generated from PHP that have their own HTML Forms (hopefully only 1 form per page).
    I’d like to add a new section to all these forms by simply adding a PHP “include” of this new section or “module”. The module will output HTML and Javascript for this new section.

    The “module” has a Javascript validation function specific to this module. How can I get the existing forms to invoke the new module’s validation function (even if the existing forms have validation or not)?

    I was trying:
    <script language="javascript" type="text/javascript">
    <!–
    alert("onSubmit BEFORE=" document.forms[0].onSubmit);
    if(!document.forms[0].onSubmit){//If onSubmit was undefined
    //I would only use one method, but I tried these 2.
    //Method 1 - Failed
    document.forms[0].onSubmit = "return Mmos_validate();";

    //Method 2 - Failed
    document.forms[0].onSubmit = function(){
    alert("Called Mmos_validate shorthand Function");
    return Mmos_validate();
    }
    }else{
    //Method 1, only tested where onSubmit was undefined
    document.forms[0].onSubmit = " return Mmos_validate();";

    //Will multiple semicolons corrupt the script?
    //If it already had an onSubmit with a "return", my code won’t get called anyway.
    //Suggestions?
    document.forms[0].onSubmit = "; return Mmos_validate();";
    }
    alert("onSubmit AFTER=" document.forms[0].onSubmit);

    function Mmos_validate(){
    alert("Called Mmos_validate regular Function");
    return false;
    }
    //–>
    </script>

  14. Instruct Me

    It seems I needed Method 2 and also to use .onsubmit instead of .onSubmit (case sensitive).

  15. Raevel

    Another advantage of using the function name() syntax is that the name property of the variable will be set to the string value of the name (think this.constructor.name when debugging).

    On the other hand I am strongly against defining functions after they are used. Since functions aren’t constant you can override them at any time, this could cause some serious confusion even if the behavior is well defined.

    Also, your alert(baz) example won’t alert undefined since a “foo is not defined” error is thrown if you try to access an undefined variable, either you were thinking of a property, or you forgot to put var baz; before the alert.

  16. Web Design Ireland

    Thank you Dustin, I could always use more types of js tips.

Get "JavaScript Design Patterns"

"As a web developer, you'll already know that JavaScript™ is a powerful language, allowing you to add an impressive array of dynamic functionality to otherwise static web sites. But there is more power waiting to be unlocked--JavaScript is capable of full object-oriented capabilities, and by applying OOP principles, best practices, and design patterns to your code, you can make it more powerful, more efficient, and easier to work with alone or as part of a team."

Buy JS Design Patterns from Amazon.com Buy JS Design Patterns from Apress

All content copyright © 2003 - 2009 under the Creative Commons License.

Archives | Blog Search