【问题标题】:Javascript Hoisting in Chrome And FirefoxChrome 和 Firefox 中的 Javascript 提升
【发布时间】:2012-12-23 22:10:43
【问题描述】:

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

(function() {

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

    })();

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

为什么不一样?

【问题讨论】:

    标签: javascript google-chrome firefox hoisting


    【解决方案1】:

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

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

    famous Kangax article on function expressions 提供了一些额外的细节:

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

    同一篇文章还说:

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

    【讨论】:

      【解决方案2】:

      来自 V8(Chrome JavaScript 引擎)bug tracker

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

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

      【讨论】:

        【解决方案3】:

        这是由于 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 版

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-06-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-20
          相关资源
          最近更新 更多