需要帮助理解Javascript中的(词法)变量作用域

3

我有一个.js文件,使用NodeJS执行。以下是我的文件内容:

var ctry = "America";

function outer(msg) {
    console.log(msg + " " + ctry) ;
    var ctry = "Canada" ;
}
outer("God Bless");

当我运行这个文件时,我期望看到的是 "上帝保佑美国",但实际上我看到的是 "上帝保佑未定义"。
如果我注释掉内部的 var ctry = 行,我会得到 "上帝保佑美国",如果我将内部的 var ctry = 行移到 console.log 上面,我会得到 "上帝保佑加拿大"。这两种情况似乎很合理,但为什么在 console.log 之后变量 ctry 的定义会导致上面的代码中 ctry 被设置为 undefined?
2个回答

5

一个局部变量的作用域(在你的情况下是ctry)是它所声明的整个函数(也就是说,就像变量在函数顶部声明一样)。你上面的代码在语义上与以下代码相同:

function outer(msg) {
    var ctry ;
    console.log(msg + " " + ctry) ;
    ctry = "Canada" ;
}

现在应该清楚为什么输出中会出现undefined

为了澄清,任何变量声明都会被提升到函数顶部。实际的赋值发生在它所在的行上。你正在重新声明变量作为局部变量,而不是使用全局变量,因为你使用了关键字var。如果你没有使用关键字var重新声明ctry,它将按照你预期的方式使用全局变量。 - dqhendricks
是的。我以为函数定义会被提升,但不知道 var 声明(局部变量)也会被提升。谢谢。 - bachposer

2
当你在函数内部使用var ctry,无论在函数的哪个位置,任何对ctry的调用(同样不管在哪)都将引用内部变量,而不是全局变量。问题是,JS解释器只看到一个变量的定义,但在执行该行之前不会将其初始化为值(Canada),所以在console.log中它仍然是未定义的。

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