令人惊讶的是,全局变量在JavaScript中具有未定义的值

iam*_*der 79 javascript scope

今天,当我看到全局变量undefined在某些情况下具有价值时,我完全感到惊讶.

例:

var value = 10;
function test() {
    //A
    console.log(value);
    var value = 20;

    //B
    console.log(value);
}
test();
Run Code Online (Sandbox Code Playgroud)

输出为

undefined
20
Run Code Online (Sandbox Code Playgroud)

这里,为什么JavaScript引擎将全球价值视为undefined.我知道JavaScript是一种解释型语言.如何在函数中考虑变量?

这是JavaScript引擎的陷阱吗?

Jos*_*ber 165

这种现象称为:JavaScript Variable Hoisting.

您在任何时候都无法访问函数中的全局变量; 你只是访问本地value变量.

您的代码等同于以下内容:

var value = 10;

function test() {
    var value;
    console.log(value);

    value = 20;
    console.log(value);
}

test();
Run Code Online (Sandbox Code Playgroud)

你还在惊讶undefined吗?


说明:

这是每个JavaScript程序员迟早都会遇到的问题.简单地说,无论您声明的变量是什么,总是被提升到本地闭包的顶部.所以,即使你在第一次console.log调用之后声明了你的变量,它仍然被认为是在你之前声明它.
但是,只有声明部分被吊起; 另一方面,这项任务并非如此.

因此,当您第一次调用时console.log(value),您引用了本地声明的变量,该变量尚未分配给它; 因此undefined.

这是另一个例子:

var test = 'start';

function end() {
    test = 'end';
    var test = 'local';
}

end();
alert(test);
Run Code Online (Sandbox Code Playgroud)

您认为这会引起什么警觉?不,不要只是继续阅读,想一想.有什么价值test

如果你说了别的话start,你错了.上面的代码相当于:

var test = 'start';

function end() {
    var test;
    test = 'end';
    test = 'local';
}

end();
alert(test);
Run Code Online (Sandbox Code Playgroud)

这样全局变量永远不会受到影响.

正如您所看到的,无论您将变量声明放在何处,它总是被提升到本地闭包的顶部.


边注:

这也适用于功能.

考虑一下这段代码:

test("Won't work!");

test = function(text) { alert(text); }
Run Code Online (Sandbox Code Playgroud)

这会给你一个参考错误:

未捕获的ReferenceError:未定义测试

这引发了很多开发人员,因为这段代码工作正常:

test("Works!");

function test(text) { alert(text); }
Run Code Online (Sandbox Code Playgroud)

如上所述,其原因是因为分配部分没有被吊起.所以在第一个例子中,当test("Won't work!")运行时,test变量已经被声明,但尚未分配给它的函数.

在第二个例子中,我们没有使用变量赋值.相反,我们正在使用正确的函数声明语法,它确实完全提升了函数.


Ben Cherry撰写了一篇很好的文章,题目是JavaScript范围和提升.
阅读.它将全面展示您的全貌.

  • 这是一个很好的解释.但是,我错过了一个解决方案,您可以在其中访问函数内的全局变量. (26认同)
  • 访问全局可变使用window.value (4认同)
  • 是的,为什么开幕式的案例A不起作用并说它未定义?我明白,它将被解释为局部变量而不是全局变量,但它将如何变得全球化? (3认同)
  • 这种变量提升方式是什么时候实现的?这一直是 javascript 的标准吗? (2认同)

Ama*_*nus 48

我对这里的问题有所解释感到有些失望,但没有人提出解决方案.如果要在函数范围内访问全局变量而不使函数首先生成未定义的局部变量,请将var引用为window.varName

  • 是的,其他人没有提出解决方案很糟糕,因为这是谷歌搜索结果的第一个结果.他们几乎回答了关于它是js引擎中的陷阱的实际问题....叹息 - >感谢您的回答 (8认同)
  • 这就是理论知识与完成之间的区别.谢谢你的回答! (2认同)

Tom*_*icz 10

JavaScript中的变量始终具有功能范围.即使它们是在函数的中间定义的,它们之前也是可见的.功能提升可以观察到类似的现象.

话虽这么说,第一个console.log(value)看到value变量(阴影外部的内部变量value),但尚未初始化.您可以将其视为所有变量声明都隐式移动到函数的开头(不是最内部的代码块),而定义则保留在同一位置.

也可以看看