这种行为有什么解释?(什么时候创建函数?)

mal*_*ree 5 javascript function

有问题的代码很简单:

console.log("So it begins.");
foo();
function foo() { console.log("In foo()."); }
console.log("So it ends.");
Run Code Online (Sandbox Code Playgroud)

为什么foo()在定义之前执行(回顾性编辑:在Chrome和Safari中)?

我对此进行了修改,在Chrome,Safari和Firefox中测试了以下代码:

javascript:foo();function foo() { alert("Oh."); }
Run Code Online (Sandbox Code Playgroud)

Chrome和Safari中会显示提醒,而Firefox则保持静音.

这种令人惊讶的,不一致的行为有什么解释吗?

bin*_*ous 8

Javascript delarations总是会被移到顶部.它被称为吊装:

应该适用于所有浏览器的示例:http: //jsbin.com/abelus/edit

  • 首先,谢谢.其次,不,它在所有浏览器中都不起作用 - 至少在撰写本文时.我已经测试了你在Firefox 6.0.2上链接的示例代码,并且没有显示"hello". (2认同)

CMS*_*CMS 3

虽然其他人解释了函数的“提升”行为(我个人认为称之为上下文准备预处理提升更清楚),但 Firefox 不同行为的原因仍然没有答案。

首先,您应该知道函数声明和函数语句之间的区别之间的区别。

正如您的示例中所示,函数声明只能发生在两个位置:全局代码中(在任何函数之外)以及直接在另一个函数的函数体内,例如:

function foo () {}

function bar () {
  function baz() {}
}
Run Code Online (Sandbox Code Playgroud)

以上所有函数都是有效的函数声明。

ECMAScript 规范不允许在其他地方定义函数声明,例如在块内:

if (true) {
  function foo () {}
}
Run Code Online (Sandbox Code Playgroud)

上面的函数应该给你一个SyntaxError例外,但大多数实现都是仁慈的,它们仍然会预处理(提升)函数,即使实际函数不可访问(例如if (false) { function bar() {} })。

在 Firefox 中,允许使用函数语句,这意味着函数定义实际上在控件到达该特定语句时发生,例如:

if (true) {
  function foo () { return true; }
} else {
  function foo () { return false; }
}
Run Code Online (Sandbox Code Playgroud)

foo();在上述语句之后执行,在 Firefox 中会产生true,因为该if语句的第一个分支实际上被执行了。

在其他浏览器中,foo();会生成false,因为所有函数在进入执行上下文时都会进行预处理,并且最后一个函数将优先,即使从未到达语句false的分支。if

Firebug 控制台执行将其包装在块内的代码,这就是该函数声明之前try-catch不可用的原因。

如果您在控制台上尝试:

console.log(typeof f); // "undefined"
function f () {}
Run Code Online (Sandbox Code Playgroud)

您将看到f尚未准备好,但如果将代码包装在函数内,您将看到预期的行为:

(function () {
  console.log(typeof f); // "function"
  function f () {}
})();
Run Code Online (Sandbox Code Playgroud)

同样,这是因为 nowf被定义为函数声明,因为它存在于匿名函数的主体中,并且不是语句块的一部分。