11

在 Chrome 和 Firefox 中运行它会给出不同的答案:

(function() {

        if(true) {
            function f() { alert("yes"); };
        } else {
            function f() { alert("no"); };
        }
        f();

    })();

在 Chrome 中,结果为“否” 在 Firefox 中,结果为“是”

为什么有区别?

4

3 回答 3

13

在条件语句中声明函数是非标准的,所以不要这样做。这是一个已知问题。您可以使用函数表达式而不是声明:

var f;
if(true) {
    f = function() { alert("yes"); };
} else {
    f = function() { alert("no"); };
}
f();

关于函数表达式的著名 Kangax 文章提供了一些额外的细节:

FunctionDeclarations只允许出现在ProgramFunctionBody中。从语法上讲,它们不能出现在Block ({ ... })中——例如 of if, whileorfor语句。这是因为Blocks只能包含Statements,而不是SourceElements,它是FunctionDeclaration

同一篇文章还说:

值得一提的是,根据规范,允许实现引入语法扩展(参见第 16 节),但仍然完全符合。这正是如今许多客户所发生的事情。其中一些将块中的函数声明解释为任何其他函数声明——只需将它们提升到封闭范围的顶部;其他——引入不同的语义并遵循稍微复杂的规则。

于 2013-01-09T17:06:45.497 回答
5

从 V8(Chrome JavaScript 引擎)错误跟踪器

不是错误。Firefox 是唯一能满足您期望的浏览器。

Safari 和 IE 在这方面的行为与 Chrome/V8 的相同。

于 2013-01-09T17:08:55.537 回答
2

这是由于 Firefox 缺少 ECMAScript 5 中所设想的函数提升而发生的。

Chrome 在运行函数体之前正确地为 f() 分配了一个值,因此 f() 的第一个版本被第二个版本覆盖。

SpiderMonkey(Firefox 的 JavaScript 引擎)运行代码时没有预先为 f() 赋值,因此它使用在其途中遇到的唯一值:function f() { alert("yes"); };

什么是功能提升?
JavaScript 的函数作用域意味着在函数中声明的所有变量在整个函数体中都是可见的。奇怪的是,这意味着变量在声明之前甚至是可见的。JavaScript 的这个特性被非正式地称为提升:JavaScript 代码的行为就像函数中的所有变量声明(但不是任何关联的赋值)都被“提升”到函数的顶部。

资料来源:
http
://statichtml.com/2011/spidermonkey-function-hoisting.html 2011 - o'reilly - javascript - 权威指南第 6 版

于 2014-09-01T12:03:46.627 回答