whats the difference between function foo(){} and foo = function(){}?

Possible Duplicate:
JavaScript: var functionName = function() {} vs function functionName() {}

are they the same? I've always wondered


No, they're not the same, although they do both result in a function you can call via the symbol foo . One is a function declaration, the other is a function expression. They are evaluated at different times, have different effects on the scope in which they're defined, and are legal in different places.

Quoting my answer to this other question here (edited a bit for relevance), in case the other question were ever removed for some reason (and to save people following the link):


JavaScript has two different but related things: Function declarations, and function expressions. There are marked differences between them:

This is a function declaration:

function foo() {
    // ...
}

Function declarations are evaluated upon entry into the enclosing scope, before any step-by-step code is executed. The function's name ( foo ) is added to the enclosing scope (technically, the variable object for the execution context the function is defined in).

This is a function expression (specifically, an anonymous one, like your quoted code):

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

Function expressions are evaluated as part of the step-by-step code, at the point where they appear (just like any other expression). That one creates a function with no name, which it assigns to the foo variable.

Function expressions can also be named rather than anonymous. A named one looks like this:

var x = function foo() {  // Valid, but don't do it; see details below 
    // ...
};

A named function expression should be valid, according to the spec. It should create a function with the name foo , but not put foo in the enclosing scope, and then assign that function to the x variable (all of this happening when the expression is encountered in the step-by-step code). When I say it shouldn't put foo in the enclosing scope, I mean exactly that:

var x = function foo() {
    alert(typeof foo); // alerts "function" (in compliant implementations)
};
alert(typeof foo);     // alerts "undefined" (in compliant implementations)

Note how that's different from the way function declarations work (where the function's name is added to the enclosing scope).

Named function expressions work on compliant implementations, but there used to be several bugs in implementations in the wild, most especially Internet Explorer 8 and earlier (and some early versions of Safari). IE8 processes a named function expresssion twice: First as a function declaration (upon entry into the execution context), and then later as a function expression, generating two distinct functions in the process. (Really.)

More here: Double take and here: Named function expressions demystified


NOTE: The below was written in 2011. In 2015, function declarations in control blocks were added to the language as part of ECMAScript 2015. Their semantics vary depending on whether you're in strict or loose mode, and in loose mode if the environment is a web browser. And of course, on whether the environment you're using has correct support for the ES2015 definition for them. (To my surprise, as of this writing in July 2017, Babel doesn't correctly transpile them, either.) Consequently, you can only reliably use function declarations within control-flow structures in specific situations, so it's still probably best, for now, to use function expressions instead.

And finally, another difference between them is where they're legal. A function expression can appear anywhere an expression can appear (which is virtually anywhere). A function declaration can only appear at the top level of its enclosing scope, outside of any control-flow statements. So for instance, this is valid:

function bar(x) {
    var foo;

    if (x) {
        foo = function() {  // Function expression...
            // Do X
        };
    }
    else {
        foo = function() {  // ...and therefore legal
            // Do Y
        };
    }
    foo();
}

...but this is not, and does not do what it looks like it does on most implementations:

function bar(x) {

    if (x) {
        function foo() {  // Function declaration -- INVALID
            // Do X
        }
    }
    else {
        function foo() {  // INVALID
            // Do Y
        }
    }
    foo();
}

And it makes perfect sense: Since the foo function declarations are evaluated upon entry into the bar function, before any step-by-step code is executed, the interpreter has no idea which foo to evaluate. This isn't a problem for expressions since they're done during the control-flow.

Since the syntax is invalid, implementations are free to do what they want. I've never met one that did what I would have expected, which is to throw a syntax error and fail. Instead, nearly all of them just ignore the control flow statements and do what they should do if there are two foo function declarations at the top level (which is use the second one; that's in the spec). So only the second foo is used. Firefox's SpiderMonkey is the standout, it seems to (effectively) convert them into expressions, and so which it uses depends on the value of x . Live example.


我在提出非常类似的问题时得到了一个很好的解释:JavaScript中有两个同名的函数 - 这怎么能工作?

链接地址: http://www.djcxy.com/p/96300.html

上一篇: Javascript函数范围和提升

下一篇: 函数foo(){}和foo = function(){}之间的区别是什么?