为什么定义为全局变量的变量是未定义的?

34

我这里有一个简单的函数和一个全局变量。

为什么mynameundefined而不是字符串"global"

var myname = "global"; // global variable
function func() {
    alert(myname); // "undefined"
    var myname = "local";
    alert(myname); // "local"
}
func();

无法引用定义在函数范围之外的外部变量吗?这个变量是全局的...

我该如何修复这个问题,以避免从全局变量中获得“undefined”?


我猜你忘记在全局变量上加上“var”了。 - crc442
我相信@crc442是正确的。你能发一下你的错误信息来确认一下吗? - mas4
2
@crc442 - 我相信你不知道你在说什么。 - Scott Selby
2
全局变量上的“var”是可选的,但不是良好的实践。 - Yogi
1
哦!我完全忘记了。那是我的调试本能在说话。对此我很抱歉。 - crc442
显示剩余2条评论
3个回答

74

你刚刚遇到了JavaScript中的“特性”——变量提升

var myname = "global"; // global variable
function func() {
    alert(myname); // "undefined"
    var myname = "local";
    alert(myname); // "local"
}
func();

在这段代码中,当你定义 func 时,编译器会查看函数体。它会发现你声明了一个名为 myname 的变量。

Javascript通过将声明移动到函数顶部来提升变量和函数的声明。

由于提升,您的代码被重写为以下形式。

var myname = "global"; // global variable
function func() {
   var myname; //declare local variable and assign it undefined
   alert(myname); // "undefined"
   myname = "local"; // assign local var myname to "local"
   alert(myname); // "local"
}
func();

这里所说的“Covers”是指覆盖全局变量。如果你想在函数范围内访问全局变量,请使用this关键字。

var myname = "global"; // global variable
function func() {
    var myname = "local";
    alert(this.myname); // "global"
    alert(myname); // "local"
}
func();
注意,这仅适用于调用函数而不是方法或构造函数,因为this关键字会根据如何调用函数来更改其绑定方式。
编辑:为了完整性
如果您想在任何上下文中访问全局变量,而不管函数类型,则声明一个按照约定从不覆盖的全局变量。
var global = this; // in global scope.
var myname = "global";
var obj = {f: function () {
    var myname = "local";
    console.log(global.myname);
}};
obj.f(); // "global"

请注意,这是在方法位置中,this关键字直接指向obj,并且因此没有定义myname。


这是正确的答案,我搞错了。 - Scott Selby
谢谢您的解释,我明白了。不过我有一个问题。为什么在函数的第三行中声明和赋值被分开了呢? - Dũng Trần Trung
1
@codingpuss hoisting不会移动赋值发生的位置。它只是复制函数中所需的变量,并在顶部声明它们。 - t3dodson
1
@Preza8 JS是在一周内设计出来的。考虑到这一点,我认为它相当不错。 - t3dodson
@t3dodson 我也听说过这个,还有其他消息来源告诉我这不是真的。但这不是重点。我认为这不是一个有效的借口。JS现在比一周前要老得多,他们有很多时间来修复像这样的问题,这些问题超出了想象。这不是一个有效的借口的另一个原因是,它可能不应该在只工作了一周后就被发布。想象一下汽车设计师说:“我们在一周内设计出来的,所以考虑到这一点,它几乎无法启动是可以接受的。” - Preza8
显示剩余2条评论

3

在函数中,您声明var myname = "local"。尽管您是在方法的中间这样做的,但该变量具有函数作用域,因此它属于整个函数,甚至是其上方的代码。

因此,在该行之前,局部变量的值为undefined,在该行之后,它具有一个值,但两者都没有触及全局变量。


我认为你回答中的这一部分并不准确:“因此,在该行之前,局部变量的值未定义...”。在JavaScript中,var语句被移动到顶部(提升),因此它会在其作用域内的任何其他代码之前执行(在这种情况下是函数)。 - Dũng Trần Trung
作为一名新手程序员,无论我阅读了多少个答案,都无法解决这个问题。问题在于我假设每次想要修改变量时,都必须以 var 开头(例如 var myVariable = 1;var myVariable = myVariable + 3;),但实际上,你只需要在第一次初始化变量时才放置 var。之后的所有时间,您需要仅使用变量名称开始该行并删除 var(例如 var myVariable = 1;myVariable = myVariable + 3;)。 (否则会出现此类问题) - gamingexpert13

0
第一个警告未定义的原因是因为您在函数中以下面一行将global重新声明为局部变量。在 JavaScript 中,这意味着从函数顶部开始,它被视为局部变量。
下面的警告有效,因为在警告正上方,您给它赋了一个值。

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