Javascript 为什么条件块中的函数声明被提升到Chrome中的函数范围,而不是Firefox中的函数范围?

Javascript 为什么条件块中的函数声明被提升到Chrome中的函数范围,而不是Firefox中的函数范围?,javascript,google-chrome,firefox,Javascript,Google Chrome,Firefox,为什么以下代码在Chrome和Firefox之间输出不同的结果 f = function() {return true;}; g = function() {return false;}; (function() { if (g() && [] == ![]) { f = function f() {return false;}; function g() {return true;} } })(); console.log(f

为什么以下代码在Chrome和Firefox之间输出不同的结果

f = function() {return true;}; 
g = function() {return false;}; 
(function() { 
   if (g() && [] == ![]) { 
      f = function f() {return false;}; 
      function g() {return true;} 
   } 
})(); 
console.log(f());
在Chrome中:结果为
false
。然而,在Firefox中,它是
真的

以上代码的关键行是第4行,根据我对功能名称提升的了解,功能
g
应该在第6行,即第2行被第6行覆盖。依我看,铬的行为是正确的


我说的对吗?如果是这样,为什么Firefox会输出不同的结果?

当前JavaScript语言的官方规范ECMAScript 5没有定义块内函数声明的行为

引述:

函数声明只允许出现在程序或函数体中。从语法上讲,它们不能出现在块中(
{…}
)-例如
if
while
for
语句。这是因为块只能包含语句,而不能包含FunctionDeclaration所定义的SourceElements。如果我们仔细研究产生式规则,我们可以看到,在块中直接允许表达式的唯一方式是当它是ExpressionStatement的一部分时。然而,ExpressionStatement被明确定义为不以“function”关键字开头,这正是FunctionDeclaration不能直接出现在语句或块中的原因(请注意,块只是语句列表)

由于这些限制,每当函数直接出现在块中时(如前一示例中),实际上应将其视为语法错误,而不是函数声明或表达式。问题是,我见过的实现中几乎没有一个严格按照规则解析这些函数(例外是BESEN和DMDScript)。他们以专有的方式解释它们

同样值得引用的是:

在第六版之前,ECMAScript规范没有将FunctionDeclaration的出现定义为块语句的StatementList元素。然而,对这种形式的FunctionDeclaration的支持是允许的扩展,大多数浏览器托管的ECMAScript实现都允许这样做。不幸的是,这些声明的语义在这些实现中有所不同。[……]


由于ES5不定义块内函数声明的行为,同时允许专有扩展,因此从技术上讲,没有“正确”或“错误”。在不同的ES5兼容环境下考虑它们“未指定的行为”。

无论如何,这些都很容易重写为可移植代码:

  • 是否应将功能声明提升到当前功能/全局范围的顶部?确保函数声明不直接位于块内部
  • 是否应该仅在执行块时声明函数?将函数表达式赋给变量(
    var f=function(){};
    )。请注意,没有提升,并且变量仍然可以在块外部访问(
    var
    声明是函数级范围)


根据ECMAScript 6,函数声明是块范围的,因此Firefox在ES6方面实现了正确的行为。

因为Chrome会提升
g
,而Firefox不会。不要在块内使用函数声明。在这种情况下,Firefox实际上更为正确,但仍然存在一些依赖于实现的魔力。看,这应该是一个答案,而不是一个评论。(虽然我认为两者或多或少都不正确,因为结果没有在规范中定义。)@iancleland:我很确定这是一个副本,但我不想在手机上搜索它。
if(g()&&&[]=![]){
可以更改为
if(g()){
这个例子仍然有效,而且在你回答的最后一句话中更清楚一点,你说函数声明是块范围的,你的意思是它们被提升到块中吗?因为MDN说的是相反的:@pooria即使MDN这么说,如果函数在块中,它们也不会被提升到程序的顶部block.@pooria在本例中也是MDN,如果block在全局范围内不可用,则函数在中。