为什么即使我之前返回,第二个函数声明也会获胜? [英] Why does second function declaration win even though I return before it?

查看:86
本文介绍了为什么即使我之前返回,第二个函数声明也会获胜?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下JavaScript代码:

I have the following JavaScript code:

(function() { 
    function f(){ alert(1); }
    return f();
    function f(){ alert(2); }
})();

你能解释为什么警报弹出2而不是1?

Can you explain why the alert pops up with 2 and not 1?

谢谢,

推荐答案

这涉及到执行进入函数时会发生什么:离开很多详细信息,处理所有函数声明(您使用的样式),并且只有之后执行逐步执行代码。所以你的 return 语句对选择哪个函数声明没有影响。并且所选择的声明始终是源代码顺序中的最后一个(这包括&mbsp;—非常粗糙的散文 —在规范的第10.5节

This gets into what happens when execution enters a function: Leaving out a lot of detail, all function declarations (the style you've used) are processed, and only after that does step-by-step code execution occur. So your return statement has no impact on which function declaration is chosen. And the declaration chosen is always the last one in source code order (this is covered — in wonderfully turgid prose — in Section 10.5 of the specification).

如果使用函数表达式,结果会有根本的不同,作为逐步代码的一部分进行评估:

The result would be fundamentally different if you used function expressions, which are evaluated as part of step-by-step code:

(function() { 
    var f;
    f = function(){ alert(1); };
    return f();
    f = function(){ alert(2); };
})();

此代码在技术上是不正确的(因为你的代码是返回将始终遵循),但它说明了差异:您看到 alert(1)发生而不是警报( 2),因为那些表达式在到达之前不会被评估。

This code is technically incorrect (because you have code following a return that will always be followed), but it illustrates the difference: You see the alert(1) happen rather than the alert(2), because those expressions are not evaluated until they're reached.

你可以阅读更多关于什么当执行进入一个函数(声明不是在第一个逐步代码之前完成的唯一事情)时,在章节 10.4.3 10.5 规范。

You can read more about what happens when execution enters a function (declarations aren't the only thing that are done prior to the first step-by-step code) in Sections 10.4.3 and 10.5 of the specification.

凭借您的新知识,测验:这里会发生什么? (注意:从不这样做。)

And with your new knowledge, a quiz: What happens here? (Note: Never do this.)

function foo() {

    if (true) {
        function bar() {
            alert(1);
        }
    }
    else {
        function bar() {
            alert(2);
        }
    }

    bar();
}

foo();

答案是: 它有所不同,请勿这样做。 有些引擎将使用第一个,其他引擎将使用第二个,其他引擎会将其称为语法错误。这是因为实际上 是一个错误,所以引擎可以自由地做他们认为最好的事情。如果仔细查看语言语法,您会发现将函数声明放在其立即包含的范围内的分支中是无效的。它们必须处于该范围的顶层。根据您对声明的新理解,原因应该是显而易见的:它们与范围内的执行流程无关,因此您无法根据执行流程选择它们。

The answer is: It varies, don't do that. Some engines will use the first bar, other engines will use the second, and others will call it a syntax error. This is because this actually is an error, and so engines are free to do what they think best. If you look closely at the language grammar, you'll see that it's invalid to put function declarations inside branches within their immediately-containing scope. They must be at the top level of that scope. With your new understanding of declarations, the reason should be obvious: They're not related to the flow of execution within the scope, and so naturally you can't choose them based on that flow of execution.

那么现实世界会发生什么?可悲的是,如果你处于松散模式(不严格),通常不会出错。一些引擎(例如Chrome的V8,在撰写本文时)将忽略流控制语句,只选择最后声明的函数(因此您得到的反直觉结果是 second bar 使用了函数),其他引擎(Firefox的SpiderMonkey,IE11的JScript)有效地重写代码,将这些声明转换为表达式,所以你得到第一个。例如,它会因引擎而异。好消息是,如果您在严格模式下尝试此操作,那么所有这三个(V8,SpiderMonkey和IE11的JScript)将失败而不是选择一个(V8和SpiderMonkey)在控制台中有明确的错误消息; JScript只有令人惊讶的 bar 未定义,但......)。

So what happens in the real world? Sadly, usually not an error if you're in "loose" mode (not strict). Some engines (Chrome's V8 for example, as of this writing) will ignore the flow control statements and just pick the last function declared (and so you get the counter-intuitive result that the second bar function is used), other engines (Firefox's SpiderMonkey, IE11's JScript) effectively rewrite your code on the fly turning those declarations into expressions instead, and so you get the first bar. E.g., it will vary by engine. The good news is that if you try this in strict mode, all three of those (V8, SpiderMonkey, and IE11's JScript) will fail rather than picking one (V8 and SpiderMonkey with nice clear error messages in the console; JScript with just the surprising "bar is undefined", but...).

如果你想做之类以上的事情,但是引擎之间有效且一致,请使用表达式:

If you want to do something like the above, but valid and consistent across engines, use expressions:

function foo() {
    var bar;

    if (true) {
        bar = function() {
            alert(1);
        };
    }
    else {
        bar = function() {
            alert(2);
        };
    }

    bar();
}

foo();

kangax的命名函数表达式揭秘页面

这篇关于为什么即使我之前返回,第二个函数声明也会获胜?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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