【问题标题】:Why JavaScript function declaration behave differently in chrome and safari? [duplicate]为什么 JavaScript 函数声明在 chrome 和 safari 中的行为不同? [复制]
【发布时间】:2017-08-25 10:40:25
【问题描述】:

    foo();

    if (true) {
      function foo() {
        console.log(1);
      }
    } else {
      function foo() {
        console.log(2)
      }
    }

在 chrome 中显示 Uncaught TypeError,但在 safari 中显示 2。

【问题讨论】:

  • 那些函数定义不会被提升,所以我希望它在任何环境中都是未捕获的类型错误。运行代码 sn-p 也会产生该错误
  • 我们不是已经对这个问题进行了很好的 QA 吗?我没有找到他们
  • @RobG 您能否详细说明一下或链接到您所指的规范部分?
  • @jakeehoffmann——给我一点时间……
  • 问题的本质是内部块中的这种函数声明(即不在范围级别)总是根据浏览器给出不同的结果。现在只是被禁止了。

标签: javascript


【解决方案1】:

这种行为有一些历史。一开始(假设 ECMA-262 ed 3,这是规范的第一个真正版本)函数声明不允许在块内(参见 Kangax, Function statements)。

然而,IE 只是将它们视为函数声明并“提升”它们,而 Mozilla 浏览器(可能是 Netscape Navigator)有条件地将它们评估为函数语句,这是规范的允许扩展。其他一些浏览器抛出错误,这可能是他们应该做的。

这种行为范围非常令人无法容忍,因此对于 ECMA-262 ed 5 aka ES5,函数语句在附录中进行了形式化(在下一版本 ECMAScript 2015 Appendix B.3.3 Block-Level Function Declarations Web Legacy Compatibility Semantics 中对其进行了更好的解释)。这可能是推动记录各种实现的作用的一部分,而不是试图严格执行违背意图但不符合规范的特定行为。

为了解决问题,严格模式下禁止使用函数语句,这也是 ECMAScript ed 5 中引入的。

如需更多阅读内容,请参阅May function declarations appear inside statements in JavaScript?,了解大约从第 5 版开始的精彩问答。

底线是,如果您想有条件地“声明”一个函数,请使用函数表达式,这样可以避免函数语句的所有问题,因为所有实现都一致地处理它们:

var someFn;

if (something) {
  someFn = function(...params1) {/*statement list 1*/};

} else {
  someFn = function(...params2) {/*statement list 2*/};   
}

从 2010 年 5 月开始,comp.lang.javascript: FAQ Topic - What is a function statement? 上有关于此主题的讨论。主要阅读 Juriy "kangax" Zaytsev 和 Richard Cornford 之间的交流,例如

Kangax:

……你的意思是——没关系——不管是不是 函数声明(在输入 上下文)或函数语句(与函数相同) 由 Function 构造函数创建的表达式和创建 在代码执行时),即它们都可以被视为 允许的扩展?

康福德:

是的,ECMA 语法不允许,所以如果他们在那里,他们 必须是扩展。允许扩展,所以两者都不能 被认为是错误的(从表面上看,即使 IE 处理命名函数 表达式为“脱离上下文”函数声明,等等 可能会产生两个函数对象,这太奇怪了 最好将其视为错误而不是扩展)。有 从来没有任何理由期待两个不同的 ECMAScript 实现具有相同的扩展,所以没有理由 期望相同的非(ECMA)标准语法产生相同的结果 两种不同环境下的行为。 (当然,如果一个环境 除了 ECMAScript 之外,还声称与 JavaScript(tm) 兼容 兼容,那么它应该复制在 JavaScript(tm))。

这几乎回答了这个问题并说明了为什么应该避免使用函数语句。

【讨论】:

  • 对我来说看起来像是 stackoverflow.com/q/8871974/218196 的副本,尽管您的回答更加详尽。
  • @FelixKling——是的,同意这一点。我不知道那个重复。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-06-29
  • 1970-01-01
  • 2012-01-05
  • 2020-05-03
  • 2014-01-08
  • 1970-01-01
相关资源
最近更新 更多