函数声明真的在变量声明之前被提升了吗?

Are function declarations really hoisted before variable declarations?

我试图了解 Javascript 中的变量提升,特别是提升函数声明和变量声明的顺序。据我了解,函数声明首先被提升,然后是变量声明。

然而,以下两个代码片段让我认为在某些情况下变量声明必须在函数声明之前:

bar();
function bar() {
  console.log(foo);
}
var foo; 

// The console will log: undefined

bar();
function bar() {
    console.log(undeclaredVariable);
}
/* As expected, the above throws:
 * "ReferenceError:  undeclaredVariable is not defined"
*/
  

在这两种情况下,函数 bar 都会被提升,因此我可以立即在第一行调用它。但是如果像 foo 这样的变量在函数之后被提升,那么 console.log(foo) 不应该在第一个片段中也抛出 ReferenceError,就像 console.log(undeclaredVariable) 在第二个片段中那样,因为它会还没有宣布?关于 Javascript 处理变量声明和提升的方式,实际顺序是什么?

函数和变量声明(但不是赋值)都被提升。

所以在这个例子中:

bar();
function bar() {
  console.log(foo);
}
var foo; 

函数声明和变量声明都被提升,然后执行类似bar();的代码。

提升发生在代码被 JIT 编译时,代码在编译后实际执行。

不,它不应该抛出错误,因为在调用 bar() 之前不会计算函数。顺序无关紧要:这些都不会引发错误:

var foo; 
function bar() {
  console.log(foo);
}
bar();

function bar() {
  console.log(foo);
}
var foo; 
bar();

因为无论提升顺序如何,名称都是在调用 bar() 并执行函数之前声明的。