根据标准,哪个JS函数声明语法是正确的?

Pac*_*ier 15 javascript firefox standards google-chrome

  var foo = function(){ return 1; };
  if (true) {
    function foo(){ return 2; }
  }
  foo(); // 1 in Chrome // 2 in FF
  //I just want to be sure, is FF 4 not "standard" in this case?
Run Code Online (Sandbox Code Playgroud)

编辑:

如果我们有这个:

  var foo = function(){ return 1; };
  if (true) function foo(){ return 2; }      
  foo(); // is 1 standard or is 2 standard?
Run Code Online (Sandbox Code Playgroud)

Jim*_*ndy 31

ECMAScript标准不允许使用原始海报的代码.(ECMAScript是JavaScript语言规范的官方名称,出于法律原因.)然而,它是语言的常见扩展 - 不幸的是,它在不同的浏览器中以不同的方式实现.

在标准JavaScript中,函数定义可能只出现在顶级代码中,或者出现在函数体的顶层.在封闭函数的主体和函数定义之间不能有条件,循环甚至花括号.

例如,允许这样做:

  function f() {
    function g() {
      ...
    }
  }
Run Code Online (Sandbox Code Playgroud)

但这不是:

  function f() {
    {
      function g() {
        ...
      }
    }
  }
Run Code Online (Sandbox Code Playgroud)

令图片复杂化的是,大多数浏览器接受后一种代码,但每种代码都为其分配了自己的特殊解释.Firefox将其视为:

  function f() {
    {
      var g = function g() {
        ...
      }
    }
  }
Run Code Online (Sandbox Code Playgroud)

ECMAScript委员会正在考虑为这些"功能陈述"选择一种特定的解释(而不是功能定义).他们还没有做出决定.Mozilla正在讨论其首选的解决方案在这里.


Bor*_*sky 16

当前ECMAScript语法实际上根本不允许使用该问题中的代码(从ECMAScript 5开始).你可以var foo = function() {}在一个块里面做,但你只能function foo() {}在函数或脚本的顶层做.

目前,浏览器以不兼容的方式支持问题中的代码,因为它们都实现了核心语言的扩展,并且实现了不同的扩展.在编译此脚本时,完全符合ECMAScript 5的实现实际上会以SyntaxError结束.

有人建议增加对ECMAScript做这种事情的能力,但它们还没有完全确定.


Mat*_*ley 12

根据ECMAScript标准,两者在技术上都是错误的,因为函数声明只允许在顶层或直接在其他函数内部.从技术上讲,if块内的函数声明是语法错误.大多数实现允许它作为扩展,但它们以不同的方式解释它.

造成这种差异的原因是Chrome将foo"声明"视为正常的函数声明并将其提升到范围的开头.Firefox(由于历史原因IIRC)仅在if语句执行时声明该函数.

为了更好地演示差异,您可以尝试运行此类似的代码:

console.log(foo()); // 2 in Chrome, error in FF

var foo = function(){ return 1; };
console.log(foo()); // 1 in both Chrome and FF

if (true) {
    function foo(){ return 2; }
}
console.log(foo()); // 1 in Chrome // 2 in FF
Run Code Online (Sandbox Code Playgroud)

编辑:你的第二个例子是完全一样的.JavaScript没有块范围,只有函数级和程序级."问题"不是函数声明在一个块中,而是它不是顶级语句.

  • +1.我认为Firefox的行为的历史原因是你可以编写`if(ie3){function f(){...}} else {function f(){...}}`而if语句将决定哪个你得到的功能.但是,它从来都不是一个理智的语言功能. (4认同)

Jef*_*den 11

对于在程序的顶级或函数体的顶层找不到的函数声明,没有指定的行为.或者说,指定的行为是语法错误,因为JavaScript语法不允许此类函数声明.不同行为的原因在于浏览器历史上一直存在于地图中,并且由于现有网站使用特定于浏览器的代码路径编写而使得任何人都无法进行更改,因此它们仍然存在.

严格模式禁止使用此语法,因为它的价值很高,ECMAScript的未来版本可能会定义它.但是现在你不应该使用它,因为它的行为不是由规范精确定义的,你会在不同的浏览器中得到不同的行为.