Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/425.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 根据标准,哪个JS函数声明语法是正确的?_Javascript_Firefox_Google Chrome_Standards - Fatal编程技术网

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

Javascript 根据标准,哪个JS函数声明语法是正确的?,javascript,firefox,google-chrome,standards,Javascript,Firefox,Google Chrome,Standards,编辑: 如果我们有: 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? 。这是未定义的行为。一团糟 firefox如何解释它由其他答案处理 chrome如何解读它 var

编辑:

如果我们有:

  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?
。这是未定义的行为。一团糟

firefox如何解释它由其他答案处理

chrome如何解读它

  var foo = function(){ return 1; };
  if (true) function foo(){ return 2; }      
  foo(); // is 1 standard or is 2 standard?
实际发生的情况是
函数foo
被声明,然后立即被局部变量
foo
覆盖

这被翻译成

var foo = function() { return 1 };
if (true) {
    function foo() {
        return 2;
    }
}
console.log(foo());

当前ECMAScript语法(从ECMAScript 5开始)实际上根本不允许使用问题中的代码。可以在块内执行
var foo=function(){}
,但只能在函数或脚本的顶层执行
function foo(){}

目前浏览器以不兼容的方式支持问题中的代码,因为它们都实现了对核心语言的扩展,并且实现了不同的扩展。编译此脚本时,完全一致的ECMAScript 5实现实际上最终会出现一个语法错误


有人提议将这类功能添加到ECMAScript中,但尚未完全定稿。

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

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

例如,这是允许的:

function foo() {
    return 2;
}
var foo;
foo = function() { return 1 };
if (true) { }
console.log(foo());
但这不是:

  function f() {
    function g() {
      ...
    }
  }
使情况复杂化的是,大多数浏览器确实接受后一种代码,但每种浏览器都为其指定自己的特殊解释。Firefox将其视为:

  function f() {
    {
      function g() {
        ...
      }
    }
  }

ECMAScript委员会正在考虑为这些“函数声明”(与函数定义相反)选择特定的解释。他们还没有做出决定。Mozilla正在讨论它的首选解决方案。

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

区别的原因是Chrome将
foo
“声明”视为一个正常的函数声明,并将其提升到范围的开头。Firefox(出于历史原因IIRC)仅在执行
if
语句时声明函数

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

  function f() {
    {
      var g = function g() {
        ...
      }
    }
  }

编辑:您的第二个示例与此完全相同。JavaScript没有块作用域,只有函数级和程序级。“问题”不在于函数声明在块中,而在于它不是顶级语句。

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


,它的价值是什么,很可能ECMAScript的未来版本会定义它。但是现在你不应该使用它,因为它的行为并不是由规范精确定义的,而且在不同的浏览器中你会得到不同的行为。

有什么原因让你期望这段代码有可预测的结果吗?@capture你发布的JSFIDLE中的代码与Pracier原始帖子中的代码不匹配。这里有一个合适的例子:我运行的是Chrome,我刚刚创建的JSFIDLE返回1,而囚徒创建的JSFIDLE返回2。@AndrewMoore函数声明被提升到最近的函数范围,而不是块范围。1是正确的。@jamietre Chromes控制台是一个不适合测试东西的地方,我过去用它遇到了很多奇怪的评估错误:/I我想大家的共识就是不要这样做!有趣的是,Firefox并没有搞错提升,而是范围界定错了。它无法提升功能,因为它位于支架内。如果删除
If(true){}
,则FF返回1。我想说的是,这个bug不太可能导致任何问题,但这引起了关于FF作用域如何工作的其他担忧。@jamietre是的,这是正确的。函数声明可能是基于块的。我查过了。只有函数声明是由块解析的。函数被绑定到函数作用域,只是在解析块之前它不会被声明。在任何情况下,任何将函数声明放在条件块中的人都应该得到它们所得到的。Firefox在这里是完全正确的。该程序不允许使用标准ECMAScript代码;相反,它使用了许多浏览器作为扩展实现的语法——每个浏览器都有不同的语义。“Firefox…[是否]范围界定错误”?给我们一点信任吧。@JimBlandy我已经搞定了答案。我不会说firefox是正确的。在块内支持函数声明是未定义的行为。但你是对的,我攻击firefox是不必要的,因为我不明白块中的函数声明是不允许的。我认为Firefox行为的历史原因是,您可以编写
if(ie3){function f(){…}或者{function f(){…}}
和if语句来确定您使用的函数。但是,它从来都不是一个健全的语言特性。我用反勾号替换管道以启用代码f
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