函数 foo(){} 和 foo = function(){} 有什么区别? [英] whats the difference between function foo(){} and foo = function(){}?

查看:21
本文介绍了函数 foo(){} 和 foo = function(){} 有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可能的重复:
JavaScript:var functionName = function() {} vs function functionName() {}

它们是一样的吗?我一直想知道

are they the same? I've always wondered

推荐答案

不,它们并不相同,尽管它们都产生了一个可以通过符号 foo 调用的函数.一个是函数声明,另一个是函数表达式.它们在不同的时间进行评估,对它们定义的范围有不同的影响,并且在不同的地方是合法的.

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 有两个不同但相关的东西:函数声明和函数表达式.它们之间存在显着差异:

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

这是一个函数声明:

function foo() {
    // ...
}

函数声明在进入封闭范围时被评估,在任何一步一步的代码被执行之前.函数的名称 (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() {
    // ...
};

函数表达式作为分步代码的一部分在它们出现的地方进行评估(就像任何其他表达式一样).该函数创建了一个没有名称的函数,并将其分配给 foo 变量.

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 
    // ...
};

根据规范,命名函数表达式应该是有效的.它应该创建一个名为 foo 的函数,但 notfoo 放在封闭的作用域中,然后将该函数分配给 x 变量(所有这些都发生在分步代码中遇到表达式时).当我说它不应该将 foo 放在封闭范围内时,我的意思是:

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).

命名函数表达式适用于兼容的实现,但在野外实现中曾经存在一些错误,尤其是 Internet Explorer 8 及更早版本(以及一些早期版本的 Safari).IE8 处理命名函数表达式两次:首先作为函数声明(进入执行上下文时),然后作为函数表达式,在这个过程中产生两个不同的函数.(真的.)

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.)

更多信息:重复 和这里:命名函数表达式揭秘

注意:以下内容写于 2011 年.2015 年,控制块中的函数声明作为 ECMAScript 2015 的一部分添加到语言中.它们的语义因您是严格还是松散模式,如果环境是网络浏览器,则处于松散模式.当然,关于您使用的环境是否正确支持 ES2015 定义.(令我惊讶的是,截至 2017 年 7 月撰写本文时,Babel 也没有正确转译它们.)因此,您只能在特定情况下可靠地使用控制流结构中的函数声明,因此目前最好还是使用函数表达式.

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();
}

这是完全有道理的:由于 foo 函数声明在进入 bar 函数时被评估,在执行任何分步代码之前,解释器不知道要评估哪个 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.

由于语法无效,实现可以自由地做他们想做的事.我从未遇到过按照我的预期执行的操作,即抛出语法错误并失败.相反,如果顶层有两个 foo 函数声明(这是使用第二个;这是在规范中),几乎所有这些都只是忽略控制流语句并做他们应该做的事情.所以只使用了第二个 foo.Firefox 的 SpiderMonkey 是最出色的,它似乎(有效地)将它们转换为表达式,因此它使用的内容取决于 x 的值.现场示例.

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.

这篇关于函数 foo(){} 和 foo = function(){} 有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆