JavaScript变量提升的解释

3

我看到了一篇关于JavaScript变量提升的文章。这篇文章总结了以下三点:

1. All declarations, both functions and variables, are hoisted to the top of the containing scope, before any part of your code is executed.
2. Functions are hoisted first, and then variables.
3. Function declarations have priority over variable declarations, but not over variable assignments.

Site Point

var showState = function() {
  console.log("Idle");
};

function showState() {
  console.log("Ready");
} 

showState(); 

我理解到代码会被JavaScript引擎解释为:
function showState() { // moved to the top (function declaration)
    console.log("Ready");
}

var showState; // moved to the top (variable declaration)
showState = function() { // left in place (variable assignment)
    console.log("Idle");
};

showState();

但是,我无法理解摘要中的第三点的含义。有人能解释一下第三点吗?第三点的含义是什么?

根据第三点的解释,以下代码片段应该返回8,函数bar()。但它显示为undefined,函数bar()。

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

在您的情况下,第3点意味着变量赋值语句 var foo 将会在您的 function bar() 被提升之前被提升。所以实际上您的代码会被解释为 var foo; function bar(),如果没有赋值语句,它将是 function bar(); var foo - AdityaParab
foo = 8; 不是变量声明,而是变量赋值。var foo; 才是变量声明的部分。 - nils
你能解释一下为什么吗?函数具有优先级是有意义的,因为它们可能会被使用。 - phoenix
@AdityaParab这是否意味着它也适用于函数表达式?因为它也有赋值。 - phoenix
我不确定为什么JS引擎实现了这个规则。我只是根据自己开发js代码的经验做出了一个猜测。在一个整洁可维护的代码中,开发人员被鼓励将方法暴露给外部世界 - 而不是变量。由于我们要暴露的是方法,因此我们不能承受在外部得到undefined。 :) 我真诚地相信这就是函数优先于未初始化变量的原因。 - AdityaParab
在变量被初始化的情况下,这意味着该变量控制了随后代码中的某些行为,因此,已初始化的变量必须优先于函数,因为这些函数“可能”需要该变量。 - AdityaParab
3个回答

2

从你链接的文章中:

In the code above we saw that the function declaration takes precedence over the variable declaration. And in the next example we’ll see that when we have function declaration versus variable assignment, the last takes priority.

var showState = function() {
  console.log("Idle");
};

function showState() {
  console.log("Ready");
} 

showState();            // output: Idle
一个函数声明有两个作用:
  1. 它声明了一个与函数同名的变量。
  2. 它将该函数分配给该变量。
这两者都被提升了,而不仅仅是变量声明。(这与具有关联赋值的var语句不同,其中只有声明被提升。)
这意味着尽管= function() {的代码处于第一位,但后面的函数声明仍然先运行,所以= function() {可以覆盖它。

1
@BRS 不,正确的解释是 function showState(){console.log("Ready");}; var showState; showState = function(){console.log("Idle");}; showState(); - frogatto
在这种情况下,变量 showState 被该赋值语句覆盖。 - frogatto
@abforce非常抱歉我理解有限。但是赋值的优先级在哪里发生? - phoenix
@BRS - 那个问题并不是一个符合英语语法的句子。 - Quentin
@Quentin 非常感谢。现在我明白了。所以代码片段 foo = 8 与第三点无关。它仅适用于同名函数。 - phoenix
显示剩余6条评论

0

你的最后一个例子被解释为

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

console.log(foo); // here 'foo' is undefined
console.log(bar); // bar is of type function
foo = 8;

应该是以下代码,因为赋值操作具有优先级: var foo; function bar() { console.log("bar"); }console.log(foo); console.log(bar); foo = 8; - phoenix
不,函数 bar 被先声明,然后才声明 foo - frogatto
那么文章摘要中第三个陈述的意义是什么呢?它是不正确的吗? - phoenix
@BRS 不,这是正确的。用户Quentin已经解释了原因。 - frogatto
Aditya的评论是无关紧要的。两个变量声明的顺序并不重要,因为它们在声明之后才会相互交互,而第三点则是在讨论赋值操作。 - Quentin
显示剩余3条评论

-1

基本上 - 假设我们有一些东西,没有特定的顺序

function hello(){};
var sup;
var yo = 4;

使用变量提升后,顺序将变为

    var yo = 4;
    function hello(){};
    var sup;

因为变量赋值具有优先级高于函数,而函数又具有优先级高于函数声明。

2
console.log(typeof hello); console.log(typeof yo); console.log(typeof sup); function hello() {} var yo = 4; var sup; 输出结果为 function, number, undefined。但是根据你的说法,第二个应该是一个数字对吧? - phoenix

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接