Reputation: 6790
I apologize in advance, this might have been discussed on StackOverflow before, I just do not know what this is called, so I could not find a satisfactory answer.
However, I am learning JavaScript and with a book called "Eloquent JavaScript". There I found the following piece of code, which repeatedly prompts the user to enter his name until he did it.
while (!input) {
var input = prompt("Who are you?");
}
I simply do not understand why this actually works instead of raising an error. At the time the condition expression is being evaluated, there is no variable called input out there. If I understand it right, there is no evaluation possible, which would normally prevent further execution. The statement in the while loop's body, which then creates a variable called input, is still being executed, though.
However, this made me anxious, so I tried this:
while (!bool) {
console.log("Hi");
var bool = true;
}
This is even weirder. It's same problem when it comes to the condition expression: bool is being created within the scope of the loop's body, after the evaluation of the condition. And secondly, bool is constantly set to be true, but still the code is being executed once, in other words, Hi is being printed once.
I am confused and would appreciate some help. ;)
Upvotes: 1
Views: 405
Reputation: 2095
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);
Upvotes: 0
Reputation: 26633
JavaScript has the unusual property that variables are scoped at the level of the function in which they are declared, not within their enclosing block (as is the case in languages like C++ and Java). This means that a variable declared within a function is in scope the instant the function begins executing, regardless of where within the body of the function the variable is declared. This behavior is sometimes referred to as "hoisting" or "lifting".
Many JavaScript programmers consider it a good practice to declare all the variables within a function at the very beginning of the function, just to avoid the strange property of having a variable in scope before it is declared.
An even more unfortunate behavior of JavaScript is that allows one to define global variables on-the-fly simply by setting them. So, if your program has no variable named input, then this code:
input = prompt("Who are you?");
Creates a global variable named input and assigns it the string returned by the prompt method. This can lead to all sorts of hard-to-debug side-effects and so is considered poor practice.
Upvotes: 1
Reputation: 1271
JavaScript does not need a variable to be declared explicitly - you can access or assign a value to the variable in before you declare it explicitly. (It has more to it, as lonesomeday has explained - I just wanted to put it simply).
When you access the variable before declaring it explicitly, it would have the value undefined.
So, in your code, try using an alert(input);
before the while
if you want to see it yourself.
Upvotes: 1
Reputation: 237885
This is one of Javascript's little eccentricities. The key thing to remember is that, in Javascript, variables are not necessarily created at the point in the code where var x =
appears. They are always created at the top of the scope. This means at the beginning of the function that contains them, or the top of the global scope if that's the scope we're working in. This is called hoisting.
So your code may look like this:
function doStuff() {
while (!bool) {
console.log("Hi");
var bool = true;
}
}
But it will run like this:
function doStuff() {
var bool = undefined;
while (!bool) {
console.log("Hi");
bool = true;
}
}
(Remember that there is no such thing as block scope in Javascript.)
The first time, bool
is undefined
. !undefined
is true
, so the conditional passes. After that, bool
is true
, so the conditional fails. It is a similar story with input
in your first example.
The variable will always be created at the very top of the scope, no matter where it is declared. For this reason, it is sometimes recommended as good practice to declare your variables at the top of the scope, since that is where Javascript will consider them to be. This prevents surprises like the one you cite.
Upvotes: 6