我提前道歉,之前可能已经在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 正在打印一次。
我很困惑,希望得到一些帮助。 ;)
答案 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中没有块范围。)
第一次bool
为undefined
。 !undefined
为true
,因此有条件的传递。之后,bool
为true
,因此条件失败。在你的第一个例子中,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);