setTimeout in javascript does not show updated value - javascript

why am I getting the outpupt 10 instead of 20. Why the setTimeout is not taking the latest value?
var a=10;
function foo(myvar){
console.log(myvar);
}
setTimeout(foo,1000,a);
a=20;
if I put setTimeout in a loop then it consoles the latest value
for (var i = 0; i < 3; i++) {
setTimeout(function log() {
console.log(i);
}, 1000);
}
3 3 3

This is because your setTimeout thread was initialized when the value for variable a is 10. There after you updated the value of variable a. But the value of parameter is still the old value 10.
var a = 10;
function foo(myvar) {
console.log('Value for param ', myvar);
console.log('Value for a ', a );
console.log('Thread Executed');
}
console.log('Thread Started');
setTimeout(foo, 1000, a);
a = 20;
console.log('Variable Updated');
What is happening in the other case was you are logging the value of the index i which is in the for loop. At the time of execution of console, the value of i will be the last value, which is 3

One issue is - you're not comparing like for like code
var a=10;
function foo(myvar){
console.log(myvar);
}
setTimeout(foo,10,a);
a=20;
is comparable to
var i;
function log(myvar) {
console.log(myvar);
}
for (i = 0; i < 3; i++) {
setTimeout(log, 10, i);
}
Whereas
for (var i = 0; i < 3; i++) {
setTimeout(function log() {
console.log(i);
}, 10);
}
Is exactly equivalent to
var i;
function log() {
console.log(i);
}
for (i = 0; i < 3; i++) {
setTimeout(log, 10);
}
and comparable to
var a=10;
function foo(){
console.log(a);
}
setTimeout(foo,10);
a=20;

You are passing a by value in the call to setTimeout(). Therefore no matter how many times you change the value of a after calling setTimeout() you'd not get any of the new values.
The following snippet would work:
var a=10;
function foo(){
console.log(a);
}
setTimeout(foo,1000);
a=20;
Because a is captured as part of the closure(foo())'s calling context. Notice that a is not passed to setTimeout() explicitly.
The second example you gave appears to work to you but it is actually exactly the same as the original sample it's just that you pass three different values - 1, 2, and 3 - to three consecutive calls to setTimeout(). If you added an if-statement inside the loop to ensure that you only call setTimeout() when i == 1 you'd see exactly the same behavior as in your first snippet.

Related

Unable to figure out the output of simple javascript code

function func2() {
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 2000);
}
}
func2();
Due to closure, the console.log statement should remember its outer lexical environment, which is first setTimeout and then the for loop. Since i is not available in the setTimeout context, it looks in the execution context of the for loop, and searches for the value of i there.
Now, that value, after 2 seconds, should have been 3 for all three executions of console.log. But it displays the output as:
0
1
2
You have used let which is block scoped so there will be separate i for each for loop iteration.
1) If you want to output consective 3 so you can declare i outside of for-loop, then there will be only single i with the value 3.
function func2() {
let i;
for (i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 2000);
}
}
func2();
2) If you want same lexical scope then you can also use var here,
var is function scoped, So there will only be one i
function func2() {
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 2000);
}
}
func2();

Can someone help me understand the output of the following code?

I've tried but every time I get a different weird output. Ideally, it should print 0, 1, 2, 3, 4 and come out of the loop but it doesn't happen.
function foo(iteration) {
if (iteration === 5) {
return;
}
for (let i = 0; i < 5; i++) {
console.log(i);
foo(iteration + 1);
}
}
foo(0);
To understand the current output, start by walking through your function step by step. It helps me to write it out and keep track of the values.
iteration starts at 0
it starts the for loop
i is 0 at this point.
its logged to the console.
foo is called again with value of 1
iteration is still less than 5
a new for loop starts. (step 2)
i is 0, this is a brand new loop since it's inside of a new instance of foo
In each iteration of the for loop, you call foo and while iteration is less than 5 you start a new for loop.
Here is an example of a function that does what you like:
function foo(iteration) {
while(iteration < 5) {
console.log(iteration)
iteration++
}
}
foo(0)
You don't need to use recursion AND a loop. Just the loop itself will work.
for (let i = 0; i < 5; i++) {
console.log(i);
}
Or, just recursion:
function foo(i) {
if (i >= 5) return true;
console.log(i);
foo(i + 1);
}
foo(0);
What you're doing is saying:
While foo-iteration is less than 5, console.log five times and start up FIVE NEW incremented foo-iterations. Each of those 5 new foo-iterations will console.log five times on their own and start up FIVE NEW incremented foo-iterations, and so on until the foo-iterations finally reach 5. Do you see how this tailspins out of control?
Since you are already using recursion, there is no need to have that loop. Something like this should work:
function foo(iteration) {
if (iteration < 5) {
console.log(iteration);
foo(iteration + 1);
}
}
foo(0)

Why is count correctly incremented

Consider this simple example:
var count = 0;
for (var i = 0; i < 4; i++ ) {
setTimeout(function() {
console.log(i, count++);
}, i * 200);
}
which outputs the following
4 0
4 1
4 2
4 3
I would guess that i always resolves to 4 because the setTimeout callback closes over the variable I but I can't figure out why the same doesn't hold true for count?
var count = 0;
for (var i = 0; i < 4; i++ ) {
setTimeout(function() {
console.log(i, count++);
}, i * 2000 );
}
The variable i is incremented by your for loop, and ends up with the value 4 before any of the timeout handlers run. The variable count, on the other hand, is only incremented inside the timeout handlers. When the first timeout handler fires, count will still be 0.
As the lads before me said, It's because the loop completes before the timeout is activated.
One way around this would be to put your timeout in a different function, and pass the i to it from within the loop. This ensures that for each iteration, the function is passed the correct i
This is also why count is set to the expected value; it lies outside of the loop's scope.
for (var i = 0; i < 4; i++) {
doSomething(i);
};
function doSomething(i) {
setTimeout(function() {
console.log(i);
}, i * 2000);
};

setInterval isn't repeating my code, but it runs once, I wonder why?

This is the code it runs perfectly once but setInterval does not repeat the second time or let's say the other consecutive times as it's suppose to, which is what I want, for example when it get's to last position of the array go back to first and so forth, can someone help me I greatly appreciate.
CSS:
#ok{position:absolute}
HTML:
<div id="ok">ok</div>
Script:
var a=[b(),c(),d()];
function b(){
for (var i=0;i<700000;i++){document.getElementById("ok").style.left=(i)+"px";}
alert(i);
};
function c(){
for (var i=0;i<20;i++){document.getElementById("ok").style.left=(i)+"px";};
alert(i);
}
function d(){
for (var i=0;i<5;i++){document.getElementById("ok").style.left=(i)+"px";alert(i)};
};
for(var i=0;i<a.length;i++){
setInterval(function(){a[i];if(i==a.length-1){i=0;};},1000);
}
Demo:
jsfiddle
There are several problems with your code. First, you're executing b() c() and d() immediately rather than on each interval. Additionally, b() c() and d() are NOT causing any kind of animation, therefore the for loops are completely pointless. Then, your for loop at the end wrapping the interval is not necessary.
http://jsfiddle.net/EBhKp/1/
var a = [b, c, d];
function b() {
document.getElementById("ok").style.left = 700000 + "px";
console.log(700000);
}
function c() {
document.getElementById("ok").style.left = 20 + "px";
console.log(20);
}
function d() {
document.getElementById("ok").style.left = 5 + "px";
console.log(5);
}
var i = 0;
setInterval(function () {
a[i]();
i++;
if (i == a.length) {
i = 0;
}
}, 1000);
A basic css transition will add the animation:
http://jsfiddle.net/EBhKp/2/
And here it is simplified:
var a = [700000, 20, 5];
function setLeftStyle(position) {
document.getElementById("ok").style.left = position + "px";
console.log(position);
}
var i = 0;
setInterval(function () {
setLeftStyle(a[i]);
i++;
if (i == a.length) {
i = 0;
}
}, 1000);
You must specify parameters when you use a function instead of use a local variable i.
Moreover, use a function pointer like this :
var a = [ b, c, d ];

Looping setTimeout

I'm currently trying to wrap my head around some JavaScript.
What I want is a text to be printed on the screen followed by a count to a given number, like so:
"Test"
[1 sec. pause]
"1"
[1 sec. pause]
"2"
[1 sec. pause]
"3"
This is my JS:
$(document).ready(function() {
var initMessage = "Test";
var numberCount = 4;
function count(){
writeNumber = $("#target");
setTimeout(function(){
writeNumber.html(initMessage);
},1000);
for (var i=1; i < numberCount; i++) {
setTimeout(function(){
writeNumber.html(i.toString());
},1000+1000*i)};
};
count();
});
This is my markup:
<span id="target"></span>
When I render the page, all I get is "Test" followed by "4".
I'm no JavaScript genius, so the solution could be fairly easy. Any hints on what is wrong is highly appreciated.
You can play around with my example here: http://jsfiddle.net/JSe3H/1/
You have a variable scope problem. The counter (i) inside the loop is only scoped to the count function. By the time the loop has finished executing, is value is 4. This affects every setTimeout function, which is why you only ever see "4".
I would rewrite it like this:
function createTimer(number, writeNumber) {
setTimeout(function() {
writeNumber.html(number.toString());
}, 1000 + 1000 * number)
}
function count(initMessage, numberCount) {
var writeNumber = $("#target");
setTimeout(function() {
writeNumber.html(initMessage);
}, 1000);
for (var i = 1; i < numberCount; i++) {
createTimer(i, writeNumber);
}
}
$(document).ready(function() {
var initMessage = "Test";
var numberCount = 4;
count(initMessage, numberCount);
});
The createTimer function ensures that the variable inside the loop is "captured" with the new scope that createTimer provides.
Updated Example: http://jsfiddle.net/3wZEG/
Also check out these related questions:
What's going on under the hood here? Javascript timer within a loop
JavaScript closure inside loops – simple practical example
In your example, you're saying "2, 3, 4 and 5 seconds from now, respectively, write the value of i". Your for-loop will have passed all iterations, and set the value of i to 4, long before the first two seconds have passed.
You need to create a closure in which the value of what you're trying to write is preserved. Something like this:
for(var i = 1; i < numberCount; i++) {
setTimeout((function(x) {
return function() {
writeNumber.html(x.toString());
}
})(i),1000+1000*i)};
}
Another method entirely would be something like this:
var i = 0;
var numberCount = 4;
// repeat this every 1000 ms
var counter = window.setInterval(function() {
writeNumber.html( (++i).toString() );
// when i = 4, stop repeating
if(i == numberCount)
window.clearInterval(counter);
}, 1000);
Hope this helps:
var c=0;
var t;
var timer_is_on=0;
function timedCount()
{
document.getElementById('target').value=c;
c=c+1;
t=setTimeout("timedCount()",1000);
}
function doTimer()
{
if (!timer_is_on)
{
timer_is_on=1;
timedCount();
}
}

Categories

Resources