alright guys. every singe time i think i understand fundamental JS quirks i go insane and realize i don't at all... while the part of this that usually stumps people DOES NOT for me... i am so confused as to why this console.logs '10' ten times. WHY is it not '9' 9 times... the loop clearly says i < 10.... i don't understand why the loop runs an extra time to ten here...
for (var i=0; i < 10; i++){
setTimeout(function(){
console.log(i);
}, 1000);
}
to add to that why does this loop below respect the i<10 thing and produce 1,2,3,4,5,6,7,8,9.. clearly in the example below the loop respects the 'until i is less than 10 (which is 9) why does it not do that in the first example and run until i is 10?
for(var i=0; i<10; i++){
console.log(i)
}
everytime i think i understand this stuff i don't its actually starting to drive me a bit insane. ive been coding over a year now and still am confused by this. i understand the call stack stuff and the closure to a degree. most people get stumped and say it will print 9 every second etc... i get that part. but why is it 10 and not 9?! also plz in layman's terms as best you can. i understand that the ++ part actually runs at the beginning of each iteration (except for the first) but i still am so confused as to why ANYTHING with closure or call stack etc would create an extra run of the loop.
also if you are REALLY up for it too... why THE F*** does this produce '1' and not '2' lol...... please answer the first question though. that is my primary confusion right now
for(let i=0; i<2; i++){
setTimeout(()=>console.log(i))
i++
}
actually at last iteration the for loop increment i value to 10. then the for loops evaluates the condition i < 10. since i is now 10 the block statement doesn't run again, but its current value is 10.
the reason the second one prints 1,2,3,4 and the first prints 10,10,10 is because the second one the code is sync, while the first one is async (setTimeout). setTimeout will be only be executed after the callstack empties. by that time i will be 10. since i is defined as var, which is not blocked scoped like let, all console.log(i) prints 10.
the second goes until the 9 because once it reaches the last iteraction i is 9 and prints 9. Then i is updated to 10 and the next block doesn't run because now i < 10 is no more valid. i is now 10 but there is no more console.log to be executed. if you console.log(i) after the for loop will print 10.
Meanwhile the async code, each setTimeout can only execute console.log once the callstack from the event loop is clear. when the event loop is clear, the for loop already has finished its execution and i is now 10. now each console.log will be executed and the value they find for i is 10.
A for loop is (more or less) the same to a while loop, and when looking at that we might find the answer:
let i = 0;
while(i < 10) {
console.log("inside loop", i); // 0,1,...,9
i++;
}
// at this point, the loop exited with i = 10
console.log("after loop", i);
On the last iteration, i is 9 when passing the body, then it gets incremented to 10, then 10 < 10 evaluates to false and the loop exits. Then somewhen the timeout calls back and 10 gets logged.
Related
I'm a very beginner learning Javascript, alongside other code languages, and while looking at information here and in other sites, I've pieced together a simple code loop:
function returnMe() {
for (let i = 1; i <= 10; i++) {
if (i == 10) return i;
console.log(i)
}
}
console.log(returnMe());
I understand what everything does except the function I've created. The function is to stop the loop from continuing endlessly, but I'm not sure how exactly I've enabled that, nor why it should be logged (though I figured out that both pieces must be there for it to work or else it will either not work or come back as undefined.)
I was hoping someone here could help quickly define the simple issue for me, since search engines and other sites believe I'm asking what the return function is instead (which makes sense why), and I just need to understand how that bit works.
the output of the function is
1
2
3
4
5
6
7
8
9
10
it will console log every number from 1 to 9 in the for loop and then it will return 10 which will be printed outside
The For Loop Consists Of for (let i = 1; i <= 10; i++) the parameters: Initiatlisation, Condition, Incrementation. So When You Use i<=10 you are allowing the function to run until the value is less than 10.
Going further It will console log all the numbers from 1 to 10 because of the console.log(i) afterwards. Then at i=10 it will return the value which will be then displayed by console.log(returnMe());
I am at a loss how best to approach for loops in JavaScript. Hopefully an understanding of for loops will help shed light on the other types of loops.
Sample code
for (var i=0; i < 10; i=i+1) {
document.write("This is number " + i);
}
My understanding is that when i has been initialized, it starts with the value of 0 which then evaluated against the condition < 10. If it is less than 10, it the executes the statement document.write("This is number + i); Once it has executed the preceding statement, only then does it increment the next value by 1.
Guides I have consulted:
http://www.functionx.com/javascript/Lesson11.htm
http://www.cs.brown.edu/courses/bridge/1998/res/javascript/javascript-tutorial.html#10.1
http://www.tizag.com/javascriptT/javascriptfor.php
Now the guide at http://www.functionx.com/javascript/Lesson11.htm seems to indicate otherwise i.e.
To execute this loop, the Start condition is checked. This is usually
the initial value where the counting should start. Next, the Condition
is tested; this test determines whether the loop should continue. If
the test renders a true result, then the Expression is used to modify
the loop and the Statement is executed. After the Statement has been
executed, the loop restarts.
The line that throws me is "If the test renders a true result, then the Expression is used to modify the loop and the Statement is executed". It seems to imply that because 0 is less than 10, increment expression is modified which would be 0 + 1 and THEN the statement, e.g. document.write is executed.
My problem
What is the correct way to interpret for loops? Is my own comprehension correct? Is the same comprehension applicable to other programming languages e.g. PHP, Perl, Python, etc?
Think of a for loop as the following
for(initializers; condition; postexec) {
execution
}
When the loop is first started the code var i = 0 is run. This initializes the variable that you will be testing for inside the loop
Next the loop evaluates the i < 10 expression. This returns a boolean value which will be true for the first 10 times it is run. While this expression keeps evaluating to true the code inside the loop is run.
document.write("This is number " + i);
Each time after this code is run the last part of the loop i++ is executed. This code in this example adds 1 to i after each execution.
After that code is executed the condition of the loop is check and steps 2 and 3 repeat until finally the condition is false in which case the loop is exited.
This the way loops work in the languages you mentioned.
Lets have a look at the corresponding section in the ECMAScript specification:
The production
IterationStatement : for ( var VariableDeclarationListNoIn ; Expressionopt ; Expressionopt) Statement
is evaluated as follows:
1. Evaluate VariableDeclarationListNoIn.
2. Let V = empty.
3. Repeat
a. If the first Expression is present, then
i. Let testExprRef be the result of evaluating the first Expression.
ii. If ToBoolean(GetValue(testExprRef)) is false,
return (normal, V, empty).
b. Let stmt be the result of evaluating Statement.
...
f. If the second Expression is present, then
i. Let incExprRef be the result of evaluating the second Expression.
ii. Call GetValue(incExprRef). (This value is not used.)
As you can see, in step 1, the variable assignment is evaluated. In step 3a, the condition is tested. In step 3b, the loop body is evaluated, and after that the third expression is evaluated in step 3f.
Therefore your understanding of the for loop is correct.
It is to assume that it works the same way in other languages, since the for loop is such a common statement in programming languages (note that Python does not have such a statement). But if you want to be absolutely certain, you better consult their specification as well.
Your quoted source is wrong, and we can prove it...
The basis of the for loop has four separate blocks which may be executed:
for(initialise; condition; finishediteration) { iteration }
Fortunately we can execute a function in each of these blocks. Therefore we can create four functions which log to the console when they execute like so:
var initialise = function () { console.log("initialising"); i=0; }
var condition = function () { console.log("conditioning"); return i<5; }
var finishediteration = function () { console.log("finished an iteration"); i++; }
var doingiteration = function () { console.log("doing iteration when `i` is equal", i); }
Then we can run the following, which places the above functions into each block:
for (initialise(); condition(); finishediteration()) {
doingiteration();
}
Kaboom. Works.
If you viewing this page using Safari on the Mac then you can AppleAlt + I and copy the above two snippets, in order, into the console and see the result.
EDIT, extra info....
Also... the finished iteration block is optional. For example:
for (var i=0; i<10;) {
console.log(i); i++;
};
does work.
The second reference is wrong. Your explanation is correct.
Another way to think about it, if this helps you:
var i = 0;
while (i < 10) {
document.write("This is number " + i);
i++;
}
This is for statement syntax:
for(initalize, condition, increment) {
Do_some_things();
}
initalize Will executed only one time when for begin then it execute Do_some_things(); statement, and while condition still true it will execute increment and then Do_some_things();. if co condition false, for would exit.
for (var i=0; i < 10; i=i+1) {
document.write("This is number " + i);
}
var i=0 will execute one time (initalize).
i < 10 condition was always checked after a loop.
i=i+1 will execute after check i < 10 and result is true.
Value of i is: 0, 1, 3, 4, 5, 6, 7, 8, 9 (10 times loop)
before you call me out for using wrong terms or sth, I am a newbie programmer.
So, this would be the correct form of the code I'm experimenting with:
for (var i = 0; i <= 10; i += 2) {
nums.push(i);
}
console.log(nums)
However, I don't get why I need to put the = sign after the +. I tried to research this but I couldn't find anything. When I removed the =, JS (Scrimba) crashed. Can anyone explain this to me please?
The third expression in the for loop is to indicate how the i variable increases. This expression is run after every loop iteration.
The second i<=10 is the condition that has to be true for the loop to continue.
Now in your loop starts with i=0, then i=2 is run after 1st iteration. And after every iteration i=2. So i<=10 is true, which is the condition. So this is an infinite loop, leading to the crash.
i+=2 is shorthand for i = i +2, so i is increasing everytime and at some point will exceed 10.
This assumes you have defined nums at top like:
var nums = []. Otherwise you get a different error.
i += 2 mean i = i + 2. In this context, for(A;B; C),C part will run every time in every loop. If you only use "+", the i value will never changed, and loop will be non-stop considering your judgement to stop the loop i < 10 equal to 0 < 10, which is true forever.
Let's take a look at for loop before go to your problem:
for (statement 1; statement 2; statement 3) {
// code block to be executed
}
Statement 1 is executed (one time) before the execution of the code block.
Statement 2 defines the condition for executing the code block.
Statement 3 is executed (every time) after the code block has been executed.
If you want to end the loop, statement 2 should return a false value.
In your case:
statement 1 is i=1 -> Assign 1 to i variable.
statement 2 is i<=10 -> Execute the code inside brackets if and only if i is less than or equal to 10
statement 3 is i+=2 -> in crease i by 2 after every run.
the point is if you change statement 3 to i+2, it is not an assignment statement anymore, but an operator. So the value of i won't be changed after statement 3 execution.
=> The value of i will always be 1
=> the statement 2 always returns true
=> infinite loop
So your code crashes because of an infinite loop
i += 2 means your are incrementing the value of i by 2.
So, in your case, the loop will start from 0, and it will push in your array. It will keep increasing your i value by 2 and pushing them in the array till it (i) becomes more than 10
for (let i=1; i<=5; i++) {
setTimeout( function timer(){
console.log( i );
}, i*1000 );
}
Biggest thing I'm confused about here - Why does this print 1,2,3,4,5 - All one second apart? Rather than incrementing one second, and taking one second longer each time we go through the for loop? I also have another variation that confuses me, where I do a console.log(i) as the last step in the for loop, and it just instantly posts 1-5. Any help here?
Coming from C#, for the record, not sure if the behaviour exists in C# or if I'm just a bit rusty.
Thanks!
It is actually quite simple. The for loop schedules the timer function for all five values. Then the timer function starts printing the numbers. Now the reason for them being printed 1 second apart is i*1000 in setTimeout. As a result, 1 will be printed 1 second after it has been scheduled, 2 will be printed 2 seconds after it has been scheduled, and approximately 1 second after 1 has been scheduled, and so on...
See the snippet below to understand how it works. Keep in mind that setTimeout does not block the execution of the for loop.
for (let i=1; i<=5; i++) {
setTimeout( function timer(){
console.log( i );
}, i*1000 );
console.log("Print " + i + " after " + i +" seconds.");
}
console.log("for loop completed.");
setTimeout() will place your timer() into the queue.
for loop execute very quickly nearly immediately, each loop timer() will be placed into the queue with delays: 1,2,3,4,5 seconds respectively.
console.log(i) will print 1-5 because of the immediate execution of for loop.
I guess what the other answers have not touched upon is the event loop.
The event loop is a distinct execution thread than the main JS thread.
Your for loop would execute in the main JS thread, pushing each timeout on the event loop which would be executed in the event loop as scheduled. The time scale of events would look something like this.
I hope this is what you are looking for
System.Threading.Thread.Sleep(1000*i);
Here I am once again. This is apparently the only way I know how to learn. What I am doing is making a for loop. Yes. Something so simple. Yet, I "have" a problem with them. More or less a problem with infinite loops. What I need to do is make a loop that counts down from 10...0. It seems easy for some of you. Yes I am very aware. I am nothing more than a student learning.
This is the code that I have:
for (var i = 11; i >= 1; i++) {
console.log(i);
}
I am stuck at this point. All that it does is crash my browser every time. Help is greatly appreciated. I would like a thorough explanation of what I am doing wrong, what I should do, and why I might have made this harder than it needed to be. Thank you!
For a loop to run from 10 to 0 iterator i should be decrementing in each iteration. But you are incrementing it instead so for loop never terminates.
for (var i = 10; i>=0; i--) {
console.log(i);
}
Everyone learns differently! In this case, you're asking the code to increment (aka add) with the ++ syntax. So, if i = 1, after i++ i = 2. Similarly i-- decrements (aka subtracts) from i.
Now, the first two parts of the loop check the value of i and continue the operation. In your case, you're asking the program set i equal to 10. If i is greater than 1, add 1 to it. That's where you're getting the infinite loop because i will always be greater than 1. What you want is. for (var i = 10; i >= 0; i--) {//code here};
You could also check out while and do/while loops.
Variable i starts at 11, and is then incremented by one each loop. Since the condition is that i >= 1, it never ends. You need to change it so that i decrements by one each loop, like this:
for (var i= 11; i>=1; i--){
First you need to learn difference between increments and decrements.
increments mean to add specific value to your variable
while on other hand decrements means to reduce the value of your variable by some specific number.
Now in your case i++ means you are adding 1 to your variable i with every iteration of loop, while to end your loop you have set the condition to i>=1
this results in an infinite loop which crashes your browser, as i would never be equal to 1 or i>=1 will never be true as with each iteration the value of i increased by 1 number, so it would continue execution, until your browser crashes.
What you are looking for is:
for (var i = 10; i >= 0; i--) {
console.log(i);
}
now i will start from 10
and will gradually reduce to 0 and your loop will end.
Hope it explained.