#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2013
    Posts
    6
    Rep Power
    0

    Function Expression vs. Function Statement


    I have a doubt about the following text from "Javascript: The Good Parts":

    The function Statement Versus the function Expression
    JavaScript has a function statement as well as a function expression. This is confusing because they can look exactly the same. A function statement is shorthand for a var statement with a function value. The statement:
    function foo( ) {}
    means about the same thing as:
    var foo = function foo( ) {};
    Throughout this book, I have been using the second form because it makes it clear that foo is a variable containing a function value. To use the language well, it is important to understand that functions are values. function statements are subject to hoisting. This means that regardless of where a
    function is placed, it is moved to the top of the scope in which it is defined. This relaxes the requirement that functions should be declared before used, which I think leads to sloppiness. It also prohibits the use of function statements in if statements. It turns out that most browsers allow function statements in if statements, but they vary in how that should be interpreted. That creates portability problems.

    The first thing in a statement cannot be a function expression because the official grammar assumes that a statement that starts with the word function is a function statement. The workaround is to wrap the whole invocation in parentheses:
    (function ( ) {
    var hidden_variable;
    // This function can have some impact on
    // the environment, but introduces no new
    // global variables.
    }() );
    MY DOUBT: I understand the first part of the above text (i.e. I understand what is a function expression and what is a function statement). The thing I don't understand is the part where Douglas Crockford is explaining an issue (I've italicized and underlined that portion) and then he proceeds to provide a workaround. Why is it a problem?
  2. #2
  3. Did you steal it?
    Devshed Supreme Being (6500+ posts)

    Join Date
    Mar 2007
    Location
    Washington, USA
    Posts
    14,007
    Rep Power
    9398
    If you just have
    Code:
    function ...
    then the Javascript parser will assume you're using a function statement. Because that's how the grammar for the language is written: a statement beginning with the token "function" is a function statement. Which means it needs a name. Wanting to allow for statements to be (the execution of) an anonymous function introduces ambiguity in the language and parsers don't like ambiguity.

    If you want an anonymous function then you can't provide a name, and thus you can't have its "function" be the first token in the statement. A perfectly harmless way of getting around that is to use parentheses because they won't affect the value of the contents (deemed an "expression").
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2013
    Posts
    6
    Rep Power
    0
    I get it but I am not completely sure. Here is what I understand: We want to use function statements in if statements. But if we use the function statement without using the parenthesis, then the parser will recognize it as a function statement and hoist it to the top of its scope (i.e. the top of the outer function's body). It will not be executed inside the if block as Javascript does not have block scope. But we want the body of the function to get executed inside the if block. So we use the parenthesis.

    Is this correct?
    Last edited by Kravvitz; January 23rd, 2013 at 04:12 PM. Reason: must we quote the whole post? :p
  6. #4
  7. Did you steal it?
    Devshed Supreme Being (6500+ posts)

    Join Date
    Mar 2007
    Location
    Washington, USA
    Posts
    14,007
    Rep Power
    9398
    Originally Posted by prachikhadke
    We want to use function statements in if statements.
    It doesn't make sense, syntactically, to put a statement within a statement. It should only be a function expression in a statement... it just gets weird because a function statement is, by itself, a valid expression as well.

    Using human language as an analogy, statements are like sentences and expressions are like nouns and verbs. You can't have a sentence within a sentence, but you can have a noun and verb (or many) within a sentence. You can even have sentences that consist entirely of a single verb.

    Originally Posted by prachikhadke
    But if we use the function statement without using the parenthesis, then the parser will recognize it as a function statement and hoist it to the top of its scope (i.e. the top of the outer function's body). It will not be executed inside the if block as Javascript does not have block scope. But we want the body of the function to get executed inside the if block. So we use the parenthesis.

    Is this correct?
    If the engine decides to hoist the function declaration (remember it's not actually valid there) then that's what it will do. Adding the parentheses forces the engine to treat it as an expression rather than as a statement.

    With all that said,
    Code:
    if (function g() { return 123; }) { console.log(true); } else { console.log(false); }
    when I execute that in Chrome 24 it does not hoist the function: it logs "true" and g is undefined. It's being treated as an expression, not a statement. If I try that in IE 9 it logs "true" but g is defined.
    Similarly,
    Code:
    var foo = function bar() { };
    in Chrome defines foo as expected but leaves bar undefined, and IE defines both.

    Comments on this post

    • ZWEI01 agrees
  8. #5
  9. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2013
    Posts
    10
    Rep Power
    0
    Originally Posted by prachikhadke
    I get it but I am not completely sure. Here is what I understand: We want to use function statements in if statements. But if we use the function statement without using the parenthesis, then the parser will recognize it as a function statement and hoist it to the top of its scope (i.e. the top of the outer function's body). It will not be executed inside the if block as Javascript does not have block scope. But we want the body of the function to get executed inside the if block. So we use the parenthesis.

    Is this correct?
    You can't use a statement inside an if statement, we use expressions. Functions inherit every scope above it, so a function A declared in global scope inherits from global scope, function B declared inside function A (which would be a function expression) inherits from the global scope and the scope of A.
    Code:
    function blah () {} //function declaration which IS a statement.
    var x = function blah() {} //statement assigning function expression to x;
    (function blah() {}) //expression
    Great resource: https://developer.mozilla.org/en-US/...function_scope
  10. #6
  11. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2013
    Posts
    6
    Rep Power
    0
    When you mention it like that (using the sentence analogy), things make more sense (i.e. why we shouldn't use function statement inside an if statement - cause both of them are statements).

    As for the browser examples, are you saying that IE9 does hoist the function expression? I can see that Chrome doesn't do that.
    Last edited by Kravvitz; January 23rd, 2013 at 04:11 PM. Reason: must we quote the whole post? :p
  12. #7
  13. Did you steal it?
    Devshed Supreme Being (6500+ posts)

    Join Date
    Mar 2007
    Location
    Washington, USA
    Posts
    14,007
    Rep Power
    9398
    Originally Posted by prachikhadke
    As for the browser examples, are you saying that IE9 does hoist the function expression?
    Apparently, yes.

IMN logo majestic logo threadwatch logo seochat tools logo