为什么一个条件块中的函数声明被提升到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中:结果是false 。 但是,在Firefox中,这是true

上面代码的关键是第4行,根据我对函数名称提示的知识,函数g应该在第6行,即第2行被第6行覆盖。IMO的行为是正确的。

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


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

引用Kangax:

FunctionDeclarations只允许出现在Program或FunctionBody中。 在语法上,它们不能出现在Block{ ... } )中,例如ifwhilefor语句。 这是因为Blocks只能包含FunctionDeclaration所在的语句,而不是SourceElements。 如果我们仔细查看生产规则,我们可以看到Expression直接在Block内被允许的唯一方式是它是ExpressionStatement的一部分。 但是,ExpressionStatement被明确定义为不以“function”关键字开头 ,这正是FunctionDeclaration不能直接出现在Statement或Block内(注意Block仅仅是一个语句列表)的原因。

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

还值得引用ECMAScript 6草案 - B.3.3块级功能声明Web遗留兼容性语义:

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


由于ES5没有在允许专有扩展的情况下为块内的函数声明定义行为,因此技术上没有“权限”或“错误”。 将它们视为“未指定的行为”,这种行为在不同的符合ES5的环境中不可移植。

无论如何,这些都很容易被重写为便携式代码:

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

  • 按照ECMAScript 6,函数声明是块范围的,所以Firefox实现了正确的ES6方式。

    链接地址: http://www.djcxy.com/p/17259.html

    上一篇: Why is a function declaration within a condition block hoisted to function scope in Chrome but not Firefox?

    下一篇: May function declarations appear inside statements in JavaScript?