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

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

问题描述


可能重复:

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


是否一样?我总是想知道它们是不是一样的,尽管它们都会产生一个函数,你可以调用这个函数。

解决方案

通过符号 foo 。一个是一个函数声明,另一个是一个函数表达式。他们在不同的时间被评估,对他们定义的范围有不同的影响,并且在不同的地方是合法的。

引用我对这个问题的回答 (编辑一下相关性),以防其他问题因为某种原因被删除(并且保存链接后的用户):




JavaScript有两个不同但相关的内容:Function 声明和函数表达式。它们之间有明显的区别:

这是一个函数声明:

函数foo(){
// ...
}

在执行任何分步代码之前,函数声明在进入封闭范围时进行评估。函数的名称( foo )被添加到封闭范围中(技术上讲,执行上下文的变量对象函数定义在)。



这是一个函数表达式(具体而言,是一个匿名函数,就像引用的代码一样):

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

函数表达式作为分步代码的一部分进行评估,在它们出现的地方(就像其他表达一样)。那个创建了一个没有名字的函数,它赋值给 foo 变量。



函数表达式也可以 而不是匿名。一个名字如下所示:

  var x = function foo(){//有效,但不要这样做;详情请见
// ...
};

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

  var x = function foo(){
alert(typeof foo); //警告函数(在兼容实现中)
};
alert(typeof foo); //警告未定义(在兼容实现中)

请注意,这与函数声明工作(函数的名称添加到封闭范围)。



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



更多信息: Double take 和这里: 命名函数表达式被揭秘






注意:下面是2011年编写的。2015年,控制块中的函数声明作为ECMAScript 2015的一部分添加到该语言中。它们的语义根据您处于严格还是松散模式而有所不同,如果环境是网络浏览器,则处于松散模式。当然,关于您使用的环境是否正确支持ES2015定义。 (令我吃惊的是,截至2017年7月的这篇文章中, Babel 也没有正确记录它们。)因此,您只能在特定情况下可靠地使用控制流结构中的函数声明,所以现在仍然可以使用函数表达式来代替它。




最后,他们之间的另一个区别是他们合法的地方。函数表达式可以出现在表达式可以出现的任何地方(几乎任何地方)。一个函数声明只能出现在任何控制流语句之外的封闭范围的顶层。例如,这是有效的:

  function bar(x){
var foo;

if(x){
foo = function(){//函数表达式...
//做X
};
}
else {
foo = function(){// ...因此合法的
// Do Y
};
}
foo();
}

...但这不是,不<在大多数实现上做它看起来像它:

 功能栏(x){
$ b $如果(x){
函数foo(){//函数声明 - INVALID
// Do X
}
}
else {
函数foo(){// INVALID
// Do Y
}
}
foo();
}

它非常合理:由于 foo 函数声明在进入 bar 函数之后进行评估,在执行任何分步代码之前,解释器不知道哪个 foo 来评估。这对于表达式来说并不是问题,因为它们是在控制流程中完成的。



由于语法无效,实现可以自由地按照自己的意愿进行操作。我从来没有遇到过这样的事情,那就是抛出语法错误而失败。相反,如果在顶层有两个 foo 函数声明(这是使用第二个;这是在规范中)。因此只使用第二个 foo 。 Firefox的SpiderMonkey是出类拔萃的,它似乎(有效地)将它们转换为表达式,所以它使用的取决于 x 的值。 现场示例


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.

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

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