2013-02-04 48 views
1

我提前道歉,这可能是之前在StackOverflow上讨论过的,我只是不知道这叫什么,所以我找不到满意的答案。JavaScript条件执行和可变范围

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

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

我只是不明白为什么这实际上工作,而不是提出一个错误。在评估条件表达式时,不存在称为输入的变量。如果我理解正确,则没有可能进行评估,这通常会阻止进一步执行。 while循环体中的语句然后创建一个名为输入的变量仍在执行中。

然而,这让我着急,所以我想这:

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

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

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

+1

那么,在你的第二个的情况下,打印后'“嗨”''bool'是'FALSE'因此'而(假)' –

+1

相关问题! :http://stackoverflow.com/questions/500431/javascript-variable-scope – ajp15243

+0

是的,但即使在打印“你好”之前,情况就是如此。它为什么一次打印出来?它从未被印过,对吧? – lambdarookie

回答

5

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

所以,你的代码可能是这样的:

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

但它会像这样运行:(记住,有没有这样的东西在Javascript块范围)

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

第一次,boolundefined!undefinedtrue,所以有条件的通行证。之后,booltrue,所以条件失败。这与第一个例子中的input类似。

变量将始终在范围内的最顶端创建,无论在声明。出于这个原因,有时候建议在变量的顶部声明变量,因为这是Javascript认为它们的地方。这可以防止您引用的意外。

+0

提升会成为变量前向声明的另一个术语吗? –

+0

感谢您快速回答!这使它很容易理解!还有一件事:我猜如果变量bool在开始时被设置为未定义,则不可能进一步评估条件表达式,因此JavaScript将认为它是真实的。那是对的吗?这可以解释为什么“嗨”打印一次。 – lambdarookie

+1

@baerenfaenger不完全。第一次,'bool'的值为'undefined',这是一个特殊的Javascript值。当它用'!'反转时,结果是'true',所以'while'测试通过。在该块中,'bool'设置为'true',所以下一次'while'测试运行时,它不会通过,因为'!true'是'false'。 – lonesomeday

1

JavaScript不需要显式声明变量 - 您可以在明确声明它之前访问变量或为其赋值。 (它有更多的东西,正如寂静的日子所解释的 - 我只是想简单地说)。

当您在明确声明变量之前访问该变量时,它的值将为undefined

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

+1

'var x = 10'不同于'x = 10'。如果没有'var',它会在首次声明时将变量放在全局范围中。 (这是不好的,除非你明确需要它在那里) – Snuffleupagus

+0

@Snuffleupagus:不知道 - 谢谢指出!现在纠正它。 – Chaithanya

1

的JavaScript具有变量在它们被声明,而不是他们的封闭块内的功能的电平范围的不寻常的特性(如在如C++和Java语言的情况下)。这意味着函数中声明的变量在函数开始执行的时间范围内,而不管函数体内声明变量的位置。此行为有时称为"hoisting" or "lifting"

许多JavaScript程序员认为这是一个很好的做法在函数的一开始就声明函数内的所有变量,只是为了避免被宣告面前有范围变量的奇特性能。

一个甚至JavaScript代码更不幸的行为是允许定义全局变量,将其设定简单地即时。所以,如果你的程序没有输入变量命名,那么这段代码:

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

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

0

有实现2位。最初,输入是未定义的,这是一个“falsy”值,所以!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);