Why does this function not increment the timeout? [duplicate] - javascript

This question already has answers here:
setTimeout in for-loop does not print consecutive values [duplicate]
(10 answers)
Closed 7 years ago.
I'm trying to figure out why this script doesn't increment the timeout by i, which is what I'd expect it to do:
for( var i=0; i<10; i++ ){
setTimeout( function(){
console.log( i );
}, i*10 );
}
This just logs 10, ten times. setTimeout should have access to i, as should the function, from what I can tell. Still, it doesn't work as I expect it to.
Here is a fiddle

The issue is that by the time the inner function gets executed, the value of i is 10, that's why you're getting 10, 10 times.
Closures 'close' over variables not over values. This means that the closure (the function inside the setTimeout) has access to the variable at the time it executes no to the value of the variable when the closure was created.
So effectively you are executing the following code:
var i;
for(i=0; i<10; i++ ){
}
// delay 0ms
console.log(i);
// some delay
console.log(i);
// some delay
....
Also remember that JS is a single threaded language, so the first setTimeout can't execute until you "yield", that means that the first function inside the setTimeout only executes when the for loop finishes, it doesn't matter how small a delay you specify in the setTimeout

You need to understand about closure. Here's the solution to your problem:
for( var i=0; i<10; i++ ){
(function(i){
setTimeout( function(){
console.log( i );
}, i*10 );
})(i);
}

Related

Javascript for loop variable scope [duplicate]

This question already has answers here:
Explanation of `let` and block scoping with for loops
(5 answers)
JavaScript closure inside loops – simple practical example
(44 answers)
let keyword in the for loop
(3 answers)
JavaScript: Understanding let scope inside for loop [duplicate]
(3 answers)
Closed 6 months ago.
This question is inspired by a very famous trick interview question for javascript closures, however I am more interested into another aspect of it. The code goes as follows:
let i
for (i = 0; i < 3; i++) {
setTimeout(function log() {
console.log(i); // What is logged?
}, 1000);
}
The answer is 3 3 3, and (I think) I know the explanation, each callback function can access the same i variable, by the time they are executed its value is 3.
When we write let inside for loop like this:
for (let i = 0; i < 3; i++) {
setTimeout(function log() {
console.log(i); // What is logged?
}, 1000);
}
Now we get 0 1 2. Ok, here the explanation is that when declared this way, i is scoped to this loop, not available outside, and each iteration has its copy of i.
The part that bugs me: it does not seem to be a different variable in each step. If we change i in a first step, it will be changed for other steps.
for (let i = 0; i < 3; i++) {
setTimeout(function log() {
console.log(i); // What is logged?
}, 1000);
if (i === 0) i ++
}
The result now is 1 2, skipped one step.
So I see two possible explanations for this, but I cannot confirm this anywhere.
Closures work differently for block-scoped and function or global scoped variable
After each step of the loop, the current state of the variable declared in a loop is copied to a new variable for the next step of the loop
???
Note: Please let's not focus on why values are 3 3 3 instead of 2 2 2, let's not go into event loop with setTimeout etc. unless relevant to the answer. I feel like closures and variable scopes will be most relevant here.

How many times function executes inside for loop? [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 2 years ago.
My question is simple if I have a for loop and I had a function inside it, how many times will the function execute.
eg:
for(i=0;i<3;i++){
console.log(i);
(function(i){
console.log(i)
})
}
If anyone has the answer can you please explain to me why?
Thanks in advance.
What about this case:
for (k=0; k<5;k++) {
$( '#a_' + k ).on('click', function() {
console.log("Clicking on a_" + k)
});
}
so when if I pass id as a_1, what will be the console print.
The anonymous function inside the for loop won't execute at all. It would have to be an immediately invoked function expression to get executed.
for(i=0;i<3;i++){
console.log(i);
(function(i){
console.log(i)
})(i); // pass (i) as argument to execute
}
What you had previously will never execute:
for(i=0;i<3;i++){
console.log(i);
(function(i){
// will never execute because this is function is never invoked
console.log(i)
})
}
In the first code snippet, the function runs 0 times. You have a function expression, but you never call it. To call it you need to add (<argument>) after the expression.
for(i=0;i<3;i++){
console.log(i);
(function(i){
console.log(i+10)
})(i)
}
In the second code snippet, all the buttons will log Clicking on a_5. Closures contain a reference to the variable, not a snapshot of its value when they were created. All the closures refer to the same k variable, and at the end of the loop it will be set to 5. So they all concatenate 5 to the log message.
See Javascript infamous Loop issue? and JavaScript closure inside loops – simple practical example for a detailed explanation and solutions.

.setTimeout function in javascript [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Function executing instantly, not waiting for setTimeout
(1 answer)
setTimeout not waiting specified time
(3 answers)
Closed 4 years ago.
could somebody help me to fully understand what is happening here please
let slideShowHandler = () => {
for(let i = 1; i <= mainElement.children.length; i++){
setTimeout(function(){
document.querySelector('#wrapper div:nth-of-type('+ i +')').style.display = "flex";
}, 3000 * i);
if(i == mainElement.children.length){
alert(i)
}
}
}
when I run the function, the alert comes up before all of the div's are displayed. I thought that it was waiting 3000ms * i and then updating i. but it looks like i goes to 4 and then the setTimeout function starts.
Any explanation to how exactly this is working would be fantastic
The function setTimeout is non-blocking and asynchronous. That is, it executes, and registers the callback function, and then happily continues to the next statement.

Explaining IIFE Inside Loop [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
How do JavaScript closures work?
(86 answers)
Closed 6 years ago.
I read this article, but I have some issues understanding it.
var funcs = [];
for (var i = 0; i < 3; i++) {
(function IIFE(arg) {
funcs[arg] = function output() {
console.log("My value: " + arg);
};
})(i);
}
for (var j = 0; j < 3; j++) {
funcs[j]();
}
How can I explain the mechanism of this snippet?
Start: i has value of 0. IIFE gets the value of i and stores it in arg.
funcs[0] just get assigned to a function named output.
second time, when i is 1, funcs[1] gets a totally new function? Is this false?
.....
The problem is here, How does funcs[0](); know that arg was 0? How things interact?
Function output() looks up and ask IIFE function to give the required value? right? Can someone say which illustration is correct?
By Providing this picture, for example, number 1, I mean, when funcs[0]() gets executed, output looks for arg, it doesn't find it, then goes to higher scope and finds it. each function has it's own IIFE, for example. I'n not sure how far are this from Javascript or even programming world, but help me get it!

How to setTimeout inside a loop [duplicate]

This question already has answers here:
Why is my function call that should be scheduled by setTimeout executed immediately? [duplicate]
(3 answers)
Closed 6 years ago.
Are you trying to set a timeout to run multiple functions with some delay between them? Is the timeout inside of a for loop? Are your functions all firing off at the same time, and not respecting the timeout, or otherwise causing messy behaviour?
It is intuitive, but incorrect to write it like this:
for (var i = 0; i < moves.length; i++) {
setTimeout(chooseOne(moves[i]), i * 1000 + 1000);
}
SOLUTION:
The solution is to pass the i values to the timeout indirectly, like this. Write the loop, call your timeout function inside the loop and pass that function the i value.
function clickedOne() {
for (var i = 0; i < moves.length; ++i) {
myTimeout(i);
}
}
then in a separate function, set the timeout, pass an anonymous function as your first parameter, inside that function I call my chooseOne function and pass it the unique value for each iteration. Now you can write a comma, and provide the second parameter for setTimeout which is your timeout. My timeout is one second times i, so each function will execute one second after the one that precedes it.
function myTimeout(i) {
setTimeout(function() { chooseOne(moves[i]); }, 1000 * i);
}
I actually don't know why this works and the first method does not.
Try this:
var i = 0;
setTimeout(function(){
if(i < moves.length){
chooseOne(moves[i++]);
}
}, i * 1000 + 1000);

Categories

Resources