Function Declarations vs. Function Expressions

Lets start with a short quiz. What is alerted in each case?:

Question 1:

function foo(){
    function bar() {
        return 3;
    }
    return bar();
    function bar() {
        return 8;
    }
}
alert(foo());

Question 2:

function foo(){
    var bar = function() {
        return 3;
    };
    return bar();
    var bar = function() {
        return 8;
    };
}
alert(foo());

Question 3:

alert(foo());
function foo(){
    var bar = function() {
        return 3;
    };
    return bar();
    var bar = function() {
        return 8;
    };
}

Question 4:

function foo(){
    return bar();
    var bar = function() {
        return 3;
    };
    var bar = function() {
        return 8;
    };
}
alert(foo());

If you didn’t answer 8, 3, 3 and [Type Error: bar is not a function] respectively, read on… (actually read on anyway 😉 )

What is a Function Declaration?

A Function Declaration defines a named function variable without requiring variable assignment. Function Declarations occur as standalone constructs and cannot be nested within non-function blocks. It’s helpful to think of them as siblings of Variable Declarations. Just as Variable Declarations must start with “var”, Function Declarations must begin with “function”.

e.g.

function bar() {
    return 3;
}

ECMA 5 (13.0) defines the syntax as
function Identifier ( FormalParameterListopt ) { FunctionBody }

The function name is visible within it’s scope and the scope of it’s parent (which is good because otherwise it would be unreachable)

function bar() {
    return 3;
}

bar() //3
bar  //function

What is a Function Expression?

A Function Expression defines a function as a part of a larger expression syntax (typically a variable assignment ). Functions defined via Functions Expressions can be named or anonymous. Function Expressions must not start with “function” (hence the parentheses around the self invoking example below)

e.g.

//anonymous function expression
var a = function() {
    return 3;
}

//named function expression
var a = function bar() {
    return 3;
}

//self invoking function expression
(function sayHello() {
    alert("hello!");
})();

ECMA 5 (13.0) defines the syntax as
function Identifieropt ( FormalParameterListopt ) { FunctionBody }

(though this feels incomplete since it omits the requirement that the containing syntax be an expression and not start with “function”)

The function name (if any) is not visible outside of it’s scope (contrast with Function Declarations).

So what’s a Function Statement?

Its sometimes just a pseudonym for a Function Declaration. However as kangax pointed out, in mozilla a Function Statement is an extension of Function Declaration allowing the Function Declaration syntax to be used anywhere a statement is allowed.  It’s as yet non standard so not recommended for production development

About that quiz….care to explain?

OK so Question 1 uses function declarations which means they get hoisted…

Wait, what’s Hoisting?

To quote Ben Cherry’s excellent article: “Function declarations and function variables are always moved (‘hoisted’) to the top of their JavaScript scope by the JavaScript interpreter”.

When a function declaration is hoisted the entire function body is lifted with it, so after the interpreter has finished with the code in Question 1 it runs more like this:

//**Simulated processing sequence for Question 1**
function foo(){
    //define bar once
    function bar() {
        return 3;
    }
    //redefine it
    function bar() {
        return 8;
    }
    //return its invocation
    return bar(); //8
}
alert(foo()); 

But…but…we were always taught that code after the return statement is unreachable

In JavaScript execution there is Context (which ECMA 5 breaks into LexicalEnvironment, VariableEnvironment and ThisBinding) and Process (a set of statements to be invoked in sequence). Declarations contribute to the VariableEnvironment when the execution scope is entered. They are distinct from Statements (such as return) and are not subject to their rules of process.

Do Function Expressions get Hoisted too?

That depends on the expression. Let’s look at the first expression in Question 2:

var bar = function() {
	return 3;
};

The left hand side (var bar) is a Variable Declaration. Variable Declarations get hoisted but their Assignment Expressions don’t. So when bar is hoisted the interpreter initially sets var bar = undefined. The function definition itself is not hoisted.

(ECMA 5 12.2 A variable with an initialzier is assigned the value of its AssignmentExpression when the VariableStatement is executed, not when the variable is created.)

Thus the code in Question 2 runs in a more intuitive sequence:

//**Simulated processing sequence for Question 2**
function foo(){
	//a declaration for each function expression
    var bar = undefined;
    var bar = undefined;
    //first Function Expression is executed
    bar = function() {
        return 3;
    };
    // Function created by first Function Expression is invoked
    return bar();
	// second Function Expression unreachable
}
alert(foo()); //3

Ok I think that makes sense. By the way, you’re wrong about Question 3. I ran it in Firebug and got an error

Try saving it in an HTML file and running it over Firefox. Or run it in IE8, Chrome or Safari consoles. Apparently the Firebug console does not practice function hoisting when it runs in its “global” scope (which is actually not global but a special “Firebug” scope – try running “this == window” in the Firebug console).

Question 3 is based on similar logic to Question 1. This time it is the foo function that gets hoisted.

Now Question 4 seems easy. No function hoisting here…

Almost. If there were no hoisting at all, the TypeError would be “bar not defined” and not “bar not a function”. There’s no function hoisting, however there is variable hoisting. Thus bar gets declared up front but its value is not defined. Everything else runs to order.

//**Simulated processing sequence for Question 4**
function foo(){
	//a declaration for each function expression
	var bar = undefined;
	var bar = undefined;
    return bar(); //TypeError: "bar not defined"
	//neither Function Expression is reached
}
alert(foo());

What else should I watch out for?

Function Declarations are officially prohibited within non-function blocks (such as if) . However all browsers allow them and interpret them in different ways.

For example the following code snippet in Firefox 3.6 throws an error because it interprets the Function Declaration as a Function Statement (see above) so x is not defined. However in IE8, Chrome 5 and Safari 5 the function x is returned (as expected with standard Function Declarations).

function foo() {
	if(false) {
		function x() {};
	}
	return x;
}
alert(foo());

I can see how using Function Declarations can cause confusion but are there any benefits?

Well you could argue that Function Declarations are forgiving – if you try to use a function before it is declared, hoisting fixes the order and the function gets called without mishap. But that kind of forgiveness does not encourage tight coding and in the long run is probably more likely to promote surprises than prevent them. After all, programmers arrange their statements in a particular sequence for a reason.

And there are other reasons to favour Function Expressions?

How did you guess?

a) Function Declarations feel like they were intended to mimic Java style method declarations but Java methods are very different animals. In JavaScript functions are living objects with values. Java methods are just metadata storage. Both the following snippets define functions but only the Function Expression suggests that we are creating an object.

//Function Declaration
function add(a,b) {return a + b};
//Function Expression
var add = function(a,b) {return a + b};

b) Function Expressions are more versatile. A Function Declaration can only exist as a “statement” in isolation. All it can do is create an object variable parented by its current scope. In contrast a Function Expression (by definition) is part of a larger construct. If you want to create an anonymous function or assign a function to a prototype or as a property of some other object you need a Function Expression. Whenever you create a new function using a high order application such as curry or compose you are using a Function Expression. Function Expressions and Functional Programming are inseparable.

//Function Expression
var sayHello = alert.curry("hello!");

Do Function Expressions have any drawbacks?

Typically functions created by Function Expressions are unnamed. For instance the following function is anonymous, today is just a reference to an unnamed function:

var today = function() {return new Date()}

Does this really matter? Mostly it doesn’t, but as Nick Fitzgerald has pointed out debugging with anonymous functions can be frustrating. He suggests using Named Function Expressions (NFEs) as a workaround:

var today = function today() {return new Date()}

However as Asen Bozhilov points out (and Kangax documents) NFEs do not work correctly in IE < 9

Conclusions?

Badly placed Function Declarations are misleading and there are few (if any) situations where you can’t use a Function Expression assigned to a variable instead. However if you must use Function Declarations, it will minimize confusion if you place them at the top of the scope to which they belong. I would never place a Function Declarations in an if statement.

Having said all this you may well find yourself in situations where it makes sense to use a Function Declaration. That’s fine. Slavish adherance to rules is dangerous and often results in tortuous code. Much more important is that you understand the concepts so that you can make your own informed decisions. I hope this article helps in that regard.

Comments are very welcome. Please let me know if you feel anything I’ve said is incorrect or if you have something to add.

See also ECMA-262 5th Edition sections 10.5, 12.2, 13.0, 13.2

90 thoughts on “Function Declarations vs. Function Expressions

  1. Nice discussion, Angus.

    I think it is important to know what the bugs with NFEs and JScript actually are, because I was originally not aware of them, and they are very subtle but dangerous (for example when doing variable shadowing). Everyone should go read the “JScript Bugs” section of Kangax’s linked article. That way you can make an educated choice on whether the risks are worth the payoff in debugging and profiling.

    In the last month or so, I have started to only use NFEs when I am explicitly debugging/profiling, and remove them when I am ready to commit.

    NFEs were just too good to be true…

    1. Hi Nick, yeah I was unaware too until alerted by Asen/Kangax. I think your strategy of NFE for development only is the only way to go right now

  2. You mention that the following values 8, 3, 3 and [Type Error: bar is not a function] should be alerted, but the value 8 is not alerted, instead it alerts 3.
    When I read the article my guess was that 3 would be alerted over 8 and after trying out your code sample in multiple browser I consistently got a 3 (as I expected.)
    How do you come to the conclusion that 8 will be alerted?

    1. Hey Bart,

      I might have misunderstood your point – but I’m going to assume you’re questioning whether/why the answer to question 1 is 8. It shows up as 8 for me on all browsers. The reason is both functions here are function declarations and function declarations get hoisted to the top of the function execution. In other words function bar is created as a function returning 3 (first fd) then immediately recreated as a function returning 8 (second fd) – then bar() is invoked

      hope this helps

  3. Hi Angus,

    Thank you for this excellent article.

    Is there a difference between Function Declarations and Function Expressions performance wise? I mean, will your code load/run faster if you use one or the other? Will the document require less memory with one or the other?

    I’m looking forward to your answer.

    Cheers,
    /andrei_aga

    1. Hi Andrei – thanks for the praise.

      I can’t imagine there is ever a significant difference between load times for FE vs. FD. Only thing to keep in mind is if you might never call the function you should probably use an FE since FDs will always be created on entering the parent function – regardless of whether you will actually use them.

      Bear in mind though that function invocation is the biggest cost and this should be identical for FE vs. FD

      Hope this helps!

  4. It does help. But here’s what I found on stackoverflow:
    The difference is that FE is defined at parse-time for a script block, whereas FD is defined at run-time. This lets you create a function and assign it to multiple event handlers without cluttering up the global namespace.
    The term “cluttering up” made me think of efficiency and that’s why I asked the question.

    Thanks for your answer.

    Cheers,
    /andrei_aga

  5. Though i tried to find what hoisted in JS means, your explanation is by far the most comprehensive and simple(the example, the analogies, etc).
    Kudos for a great article!

    Regards

  6. Thanks for sharing this, Angus! I believed to know everything about the distinction between Function Expressions and Declarations … but I didn’t. That Function Declarations are hoisted together with its body was new to me.

  7. The way you present the quiz, all the foo’s are defined in the same scope. Would this not make each alert result in a Type Error since all foo declarations would be hoisted above the alerts and thus the last one is called every time?

    Still, a very nice explanation. I would not have caught the issue I point out if I had not first read your analysis.

  8. I come from a classical language background.
    I find it interesting that bar is a global function or variable, although it is declared within foo.
    foo is a member of Window.
    Can see this in firebug.

  9. Wouldn’t we be better with something like the following:
    This way we aren’t (as Douglas Crockford puts it (and rightfully so)) clobbering the global variables.

    //Question 1
    function Foo(){
    function bar() { //private
    return 3;
    }
    this.barMeth = bar(); //privileged
    function bar() { //private
    return 8;
    }
    }
    var myFoo = new Foo();
    alert(myFoo.barMeth);

    //Question 2
    function Foo(){
    var bar = function bar() { //private
    return 3;
    }
    this.barMeth = bar(); //privileged
    var bar = function bar() { //private
    return 8;
    }
    }
    var myFoo = new Foo();
    alert(myFoo.barMeth);

    //and so on?

  10. Very clear post, thanks.
    I’m wondering however, in terms of performance – do function declarations and expressions get parsed the same number of times in all cases? Consider the following:

    function a() {
    function b() {
    // some code
    }
    }

    vs.

    function a() {
    var b = function() {
    // same code
    }
    }

    If I call a 100 times, how many times will the browser need to parse b’s code in both cases? What about if I don’t call a at all? I imagine it should be possible for the browser to parse the code at most once in both cases, but is this really the case?

    Thanks
    Spock

  11. Excellent article. Amazing how easy it is to get by on traditional javascript without ever knowing these things… Until one day you try to do things properly and realize you don’t know how anything works!

  12. Excellent article, however there is one thing worth pointing out performance-wise that I didn’t see mentioned.

    Function Declarations and Named Function Expressions both create a function object once that is re-used over and over again, whereas an Anonymous Function Expression creates a new function object every time it is executed.

    For most people this has absolutely no impact on their application’s performance, but now that single-page apps are becoming more common (leading to a page being open for a long time) and now that people are pushing the boundaries of javascript performance in HTML5 gaming and other demanding use cases, you may have to consider using Function Declaration to reduce the frequency of garbage collection pauses.

    1. malandrew:
      Are you sure about that?
      Can you provide confirmation?

      var a = function () {
      return 3;
      };

      In the above example, I would have thought that when the function is assigned to a, the function is instantiated.
      Any time a is used, I would have thought that a is executed… and the assignment is not executed again?

      1. I may have been inaccurate. Functions that return functions are definitely creating new objects (garbage) on execution and depending on whether function declarations or function expression is used, the browser engine can optimize to prevent garbage. However I may be wrong here.

        Here’s a jsperf with some scenarios. Function declarations with a closure is most performatic.
        http://jsperf.com/function-name-or-name-function/5

        I believe it the amount of garbage created and thus overall performance depend on the javascript engine optimizations. Since that jsperf shows performance varying wildly depending on the browser.

        ref: http://www.scirra.com/blog/76/how-to-write-low-garbage-real-time-javascript/

  13. I was going to say those results don’t really surprise me.
    closures are best practice for several reasons.
    A function declaration or statement will be faster than the function expression or variable declaration with function assignment…
    because there’s no assignment.

    I was using chromium.
    Then I tried in Firefox, Oh dear.
    This illustrates why I moved away from Firefox, it just felt so sluggish compared to chromium.
    What a difference in perf eh?

  14. This is a fantastic article – thanks for clearing up a lot of things for me!

    The part about variable declarations being hoisted surprised me. But it explains why I see so many ‘undefined’ variables in the inspector when I debug my Node code.

    What’s surprising is that this hoisting causes the following situation:

    (function foo(){bar = 10; var bar = 20;}());
    alert(bar) // ReferenceError: bar is not defined
    (function foo(){bar = 10;}());
    alert(bar) // 10

    Declaring the var afterwards prevents ‘bar’ from being declared as global. Pretty nuts.

    I use function declarations often when attempting to make my code a little more readable. For example, I have similar code in Tixelated:

    function loadEvent(){

    _loadBody();
    _loadSidebar();
    …etc.

    function _loadBody(){… body stuff};
    function _loadSidebar(){… sidebar stuff};
    }

    This is a simple way for me to make my really long functions just a bit more readable. I could define the functions with expressions at the top of the function, but I really don’t like the inversion – the function becomes a lot more difficult to read when you have to scroll to the bottom to figure out what it actually does.

    1. Hi Samuel,
      thanks for your kind words.

      Actually the behaviour in your example is consistent with the laws of hoisting.
      The declaration

      var bar = 20;

      is immediately hoisted – so bar is defined as a function scoped variable (with value undefined) before we encounter

      bar = 10;

      Thus the latter statement does not create a global but simply updates the existing function scoped variable.

  15. Samuel:

    If you enable strict mode… ‘use strict’;
    For the second example, you’ll always get the “bar is not defined” on browsers that support strict mode.

    To quote Stoyan Stefanov’s excellent book “JavaScript Patterns”
    Implied globals created without var (regardless if created inside functions) can be deleted.
    This shows that implied globals are technically not real variables, but they are properties
    of the global object. Properties can be deleted with the delete operator whereas variables cannot.

    I think what’s happening in your first example is; your deleting the global bar property and redefining it as a local variable.
    This explains why it’s undefined outside of foo’s scope.

    1. @binarymist:

      Your explanation is incorrect. Please see my reply to Samuel (above).

      Declaring a variable in function scope will never delete a global variable with the same name. (strict mode or not).

      Also Stoyan’s explanation of delete (at least as quoted) is a bit off the mark. While (as of ES 5), variables are never deletable, it’s also quite easy to create a non-deletable property. In fact, the distinction between properties and variables is somewhat murky, because a variable’s state is itself a property, on either the global object or on the environment record of a function scope.

      Since the ability to delete an object is solely dependent on its [[configurable]] property, the relevant consideration is how the property was originally created. Properties created using property notation are initially configurable, thus initially deletable, but can be made non-deletable (in most browsers) by flipping their [[configurable]] flag.

      The implicit global syntax used in Samuel’s example is considered property notation, thus implicit globals are initially deletable

  16. Angus:
    Of course. Your right.
    I can’t believe I missed that.

    Your reply to Samuel came in while I was posting.
    Never the less, I still got it wrong.
    It’s funny, that although I understand hoisting, have written a blog post on it, have taught developers at work about it,
    this can still be missed because it’s just not obvious.

    What I initially thought must have been happening was, that bar = 10 is not creating a global property until the function was fully defined.
    That’s bar = 10; and var bar = 20 and the end bracket was encountered or executed.
    Why, because I watched what was happening in the debugger.
    What was actually happening was a simple hoist.
    This can’t be explicitly seen, so one must just remember the rules, then it makes sense again.

    Stoyan’s explanation is based on ES3.
    The book doesn’t explore patterns related to ES5’s specific additions, because at the
    time of this writing there’s no browser that implements ES5. But the examples in this
    book promote a transition to the new standard.
    So I think it’s on the ES3 mark.
    In most cases, if you are programming to support Chrome, FF, IE incl legacy, and Opera, you won’t be using ES5 yet.

    Yeah, after some more reading, I see what you mean by murky

    ——————————————————-
    Properties

    have:

    name, and 4 attributes (value, writeable, enumerable, and configurable)

    These are data properties (prior to ES5)

    ES5

    value can be replaced by one or two methods known as a getter or setter.
    These are known as accessor properties.
    In which case the writable attribute no longer exists.
    So the four attributes of an accessor property are get, set, enumerable, and configurable

    ——————————————————-

    var propertyDescriptor_bar;
    var propertyDescriptor_globalPropNoVar;
    var propertyDescriptor_globalPropWithVar;
    var globalPropWithVar;

    var global = (function () {
    return this;
    }());

    (function foo() {
    bar = 10;
    }());

    propertyDescriptor_bar = Object.getOwnPropertyDescriptor(global, ‘bar’);
    // propertyDescriptor_bar.configurable is true

    globalPropNoVar = 9;
    // globalPropNoVar.configurable is true

    propertyDescriptor_globalPropNoVar = Object.getOwnPropertyDescriptor(global, ‘globalPropNoVar’);
    // propertyDescriptor_globalPropNoVar.configurable is true

    propertyDescriptor_globalPropWithVar = Object.getOwnPropertyDescriptor(global, ‘globalPropWithVar’);
    // propertyDescriptor_globalPropWithVar.configurable is false

  17. Yeah, we’re all only human, although as programmers we pride our selves on knowing our stuff.
    I just had a re-read of your post and realised it had changed quite a bit since my original read months ago.
    This is great, because the post ends up being a living document that’s had input from multiple sources. Which has always got to be a good thing. I notice the link within the text “and Kangax documents” seems to be broken?
    Time to subscribe to your blog

  18. I don’t know how else to say it man, you’re awesome! Another great article. The deeper I dive into the nature of JavaScript, the more I find myself on your site reading some of the best crafted articles on the web. Much appreciated!

  19. Great article. Can I just qualify something?

    Does the following (in chrome at least) return an actual named function object because of hoisting? Are you trying to highlight that, in essence, the if is ignored (at least in some instances)?

    function foo() {
    if(false) {
    function x() {};
    }
    return x;
    }
    alert(foo());

    Great post – I was just a little confused with this last part.

  20. First of all, your blog’s incredibly helpful, thanks so much! I just had a couple questions about some stuff from your post…

    function bar() {
       return 3;
    }

    (function sayHello() {
    alert(“hello!”);
    })();

    I just wanted to clarify the difference between a function declaration and a function expression in these 2 cases; does sayHello only become a function *expression* once you make it self-invoking, i.e. part of the expression to invoke sayHello as a function? So it’d be a function *declaration* like bar without the (self-)invocation, right?

    And then sayHello isn’t global-scoped (when its self-invoked as in your example) because its only visible within the scope of the larger expression (the invocation), if that makes sense? So then is the only purpose of the brackets around the invocation of sayHello is to avoid starting the expression with “function”? I think I’d got it into my head that that affected the scoping or something. :S

  21. It’s soooo confusing….i mean javascript, not your article. Different ways to declare function, inconsistent way of declaration, hoisting, different interpretation between browsers. If it’s not the only or common client script, maybe i won’t bother to learn it… damn js… anyway thanks for your article, it helps me…uhm..maybe a bit, but your article is very good, it’s just js is soooo confusing… damn js…

    1. If it was easy everyone would be doing it.
      Different ways of declaring functions provide flexibility.
      There were some bad design decisions that were made when ECMAScript was first created, we are still living with those decisions. That’s part of the fun.
      Browsers have different levels of dom support, but JavaScript is interpreted the same from browser to browser. The implementation of how the JavaScript engine interprets JavaScript differs though.
      “If it’s not the only or common client script, maybe i won’t bother to learn it”
      Well, there’s a problem, it is.
      If you invest the time into the language, you will come to see it’s beauty and where it shines.

  22. Great info, really helped me out in a confusing situation. I completely missed the quiz, but think I’d do a lot better if given a new one. 🙂

  23. Pingback: Ember.js Days
  24. When someone writes an article he/she retains the image of a user in his/her brain that how a user can know it. So that’s why this article is outstdanding. Thanks!|

  25. When you say

    “Question 3 is based on similar logic to Question 1. This time it is the foo function that gets hoisted.”

    Do you mean it’s similar logic to Question 2?

  26. Wow. This is a great article. It helped me understand and fix a bug in a 3-year old JavaScript code I had abandoned at the time after losing hours trying to understand what was going on.

  27. Awesome post! Excellent as usual.

    Please I am somewhat confused about this example –
    (function sayHello() {
    alert(“hello!”);
    })()

    Is it self-invoking or immediately invoked? The function is not calling itself inside the body. Could you please clarify? Thanks!

    1. It is same, self-invoking immediately after the function declaration. The wrapper block also useful for isolation, so the function cannot be invoked outside the block.

  28. How send a parameter while we declare it like this
    var myfunction = function () {
    // Do something
    }

    myfunction();

    i want to send parameter in myfunction like myfunction(a,b,c);

    How to work it out ?

Leave a comment