1

我提前道歉,这可能之前在StackOverflow上已经讨论过,我只是不知道这叫什么,所以我找不到满意的答案。

但是,我正在学习 JavaScript,并且正在学习一本名为“Eloquent JavaScript”的书。在那里我找到了下面的一段代码,它反复提示用户输入他的名字,直到他这样做。

while (!input) {
    var input = prompt("Who are you?");
}

我根本不明白为什么这实际上有效而不是引发错误。在评估条件表达式时,没有称为输入的变量。如果我理解正确,则无法进行评估,这通常会阻止进一步执行。不过,while 循环主体中的语句(然后创建了一个名为input的变量)仍在执行中。

但是,这让我很着急,所以我尝试了这个:

while (!bool) {
    console.log("Hi");
    var bool = true;
}

这更奇怪了。当涉及到条件表达式时,也是同样的问题:在条件评估之后,在循环体的范围内创建了bool 。其次,bool始终设置为 true,但代码仍被执行一次,换句话说,Hi被打印一次。

我很困惑,希望能得到一些帮助。;)

4

4 回答 4

6

这是 Javascript 的小怪癖之一。要记住的关键是,在 Javascript 中,变量不一定是在代码中var x =出现的位置创建的。它们总是在范围的顶部创建。这意味着在包含它们的函数的开头,或者如果这是我们正在工作的范围,则在全局范围的顶部。这称为提升

因此,您的代码可能如下所示:

function doStuff() {
    while (!bool) {
        console.log("Hi");
        var bool = true;
    }
}

但它会像这样运行:

function doStuff() {
    var bool = undefined;
    while (!bool) {
        console.log("Hi");
        bool = true;
    }
}

(请记住,Javascript 中没有块作用域之类的东西。)

第一次,boolundefined!undefinedtrue,所以条件通过。之后,boolis true,所以条件失败。input这是一个与您的第一个示例类似的故事。

变量将始终在作用域的最顶部创建,无论它在哪里声明。出于这个原因,有时建议将变量声明在作用域的顶部作为一种好习惯,因为这是 Javascript 认为它们所在的位置。这样可以防止像您引用的那样出现意外。

于 2013-02-04T22:54:37.317 回答
1

JavaScript 不需要显式声明变量 - 您可以在显式声明变量之前访问变量或为其赋值。(正如 lonesomeday 所解释的那样,它还有更多意义——我只是想简单地说)。

当您在显式声明变量之前访问该变量时,它将具有值undefined

因此,在您的代码中,如果您想自己查看,请尝试在alert(input);之前使用。while

于 2013-02-04T22:54:18.850 回答
1

JavaScript 有一个不寻常的属性,即变量的作用域是在声明它们的函数级别,而不是在它们的封闭块内(就像 C++ 和 Java 这样的语言中的情况)。这意味着在函数中声明的变量在函数开始执行的那一刻就在作用域内,而不管该变量在函数体中的哪个位置被声明。这种行为有时被称为“提升”或“提升”

许多 JavaScript 程序员认为在函数的最开始声明函数内的所有变量是一种很好的做法,只是为了避免在声明之前在范围内具有变量的奇怪属性。

JavaScript 的一个更不幸的行为是,它允许人们通过简单地设置全局变量来动态定义它们。所以,如果你的程序没有名为 input 的变量,那么这段代码:

input = prompt("Who are you?");

创建一个名为 input 的全局变量,并为其分配由 prompt 方法返回的字符串。这可能会导致各种难以调试的副作用,因此被认为是不好的做法。

于 2013-02-04T23:02:43.987 回答
0

There are 2 bits to realize. Initially, input is undefined, which is a "falsy" value, so !input evaluates to true. The second thing to realize is once the var input or var bool are assigned, they are valid at the same scope as the loop (ie just outside it), so when the loop iterates a second time the variable will be set. For the input case, anything null or undefined is considered falsy, so once the input has a value the loop will exit. You can kind of see this in this bit of code:

        while(!bar) {
        console.log('1', bar);
        var bar = true;
        console.log('2', bar);
    }
    console.log('3', bar);
于 2013-02-04T23:02:54.807 回答