为什么JavaScript函数声明在chrome和safari中表现不同?

时间:2017-03-31 08:23:41

标签: javascript



    foo();

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




在chrome中它显示Uncaught TypeError,但在Safari中它显示2。

1 个答案:

答案 0 :(得分:7)

此行为有一些历史。在开头(假设是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第5版也引入了这种语句。

如需了解更多信息,请参阅May function declarations appear inside statements in JavaScript?,了解关于Ed 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:

  

......你的意思是 - 没关系 - 是不是   一个函数声明(在输入时创建)   context)或函数语句(与函数相同)   表达式并由Function构造函数创建   在代码执行时),即它们都可以被视为公正   允许的延期?

康福德:

  

是的,如果他们在那里,ECMA语法不允许这样做   必须是扩展。允许扩展,所以也不允许   被认为是错误的(表面上看,即使IE正在处理命名函数   表达式为'out of context'函数声明,等等   潜在地产生两个函数对象,是如此无益奇怪   它会被认为是一个错误而不是扩展。)有   从来没有任何理由期待两种不同的ECMAScript   实现具有相同的扩展名,因此没有理由   期望相同的非(ECMA)标准语法产生相同的结果   两种不同环境中的行为。 (当然,如果有环境   声称除了ECMAScript之外还兼容JavaScript(tm)   兼容然后它应该再现在中发现的扩展   的JavaScript(TM))。

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

相关问题