Why JavaScript function declaration behave differently in chrome and safari?
1 2 3 4 5 6 7 8 9 10 11 | foo(); if (true) { function foo() { console.log(1); } } else { function foo() { console.log(2) } } |
在chrome中它显示Uncaught TypeError,但在Safari中它显示2。
这种行为有一些历史。在开头(比如ECMA-262 ed 3,这是规范的第一个真正版本),块内部不允许使用函数声明(参见Kangax,Function语句)。
但是,IE只是将它们视为函数声明并"提升"它们,而Mozilla浏览器(可能是Netscape Navigator)有条件地将它们作为函数语句进行评估,这是规范的允许扩展。其他一些浏览器抛出错误,这可能就是他们本应该做的。
这一系列的行为是非常难以忍受的,所以使用ECMA-262 ed 5 aka ES5,函数语句在附录中形式化(在下一版本中更好地解释了它们,ECMAScript 2015附录B.3.3块级函数声明Web遗留兼容性语义) 。这可能是推动记录各种实现的内容的一部分,而不是试图严格执行与意图相反的特定行为,而不是规范的字母。
为了解决问题,在严格模式下禁止使用函数语句,ECMAScript ed 5也引入了这种模式。
有关其他阅读,请参阅May函数声明是否出现在JavaScript中的语句中?从Ed 5时代开始,我们可以获得良好的Q& A
最重要的是,如果你想有条件地"声明"一个函数,使用函数表达式,这避免了函数语句的所有问题,因为它们一直被所有实现所处理:
1 2 3 4 5 6 7 8 | var someFn; if (something) { someFn = function(...params1) {/*statement list 1*/}; } else { someFn = function(...params2) {/*statement list 2*/}; } |
关于comp.lang.javascript的这个主题有一个讨论:FAQ主题 - 什么是函数声明?从2010年5月开始。主要阅读Juriy"kangax"Zaytsev和Richard Cornford之间的交流,例如
Kangax:
… You mean -- it doesn't matter -- whether it is
a function declaration (which is created on entering the
context) or a function statement (which the same as function
expression and created by the Function constructor is created
at code execution), i.e. both of them can be treated as just
an allowed extension?
康福德:
Yes, ECMA syntax doesn't allow for either so if they are there they
must be extensions. Extensions are allowed so neither can be
considered wrong (on the surface, even if IE's treating named function
expressions as 'out of context' function declarations, and so
potentially producing two function objects, is so unhelpfully odd that
it would be better considered a bug than an extension). There has
never been any reason for expecting two different ECMAScript
implementations to have the same extensions, so there is no reason for
expecting the same non-(ECMA)standard syntax to result in the same
behaviour in two different environments. (Of course if an environment
claims to be JavaScript(tm) compatible in addition to being ECMAScript
compatible then it should be reproducing the extensions found in
JavaScript(tm)).
这几乎解答了问题,并指出为什么应该避免函数语句。