JavaScript条件执行和变量范围

时间:2013-02-04 22:48:44

标签: javascript scope conditional-statements

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

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

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

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

然而,这让我很焦虑,所以我尝试了这个:

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

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

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

4 个答案:

答案 0 :(得分:5)

这是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,因此有条件的传递。之后,booltrue,因此条件失败。在你的第一个例子中,input就是一个类似的故事。

变量将始终在范围的最顶部创建,无论它在何处声明。出于这个原因,有时建议将变量声明在范围的顶部,因为这是Javascript认为它们的位置。这可以防止像你引用的那样的惊喜。

答案 1 :(得分:1)

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

在明确声明变量之前访问变量时,它的值为未定义

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

答案 2 :(得分:1)

JavaScript具有不寻常的属性,即变量在声明它们的函数级别范围内,而不是在它们的封闭块中(如C ++和Java等语言中的情况)。这意味着函数内部声明的变量在函数开始执行的瞬间处于范围内,无论函数体内的哪个位置声明了变量。此行为有时称为"hoisting" or "lifting"

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

JavaScript的一个更不幸的行为是允许人们通过设置它们即时定义全局变量。因此,如果您的程序没有名为input的变量,则此代码为:

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

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

答案 3 :(得分:0)

有2位要实现。最初,输入是未定义的,这是一个“虚假”值,所以!input的计算结果为true。要实现的第二件事是,一旦赋值var input或var bool,它们在与循环相同的范围内有效(即在它之外),所以当循环迭代第二次时,变量将被设置。对于输入大小写,任何null或undefined都被认为是假的,所以一旦输入有一个值,循环就会退出。您可以在这段代码中看到这一点:

        while(!bar) {
        console.log('1', bar);
        var bar = true;
        console.log('2', bar);
    }
    console.log('3', bar);
相关问题