Trouble understanding closure details - setTimeout within for loop - javascript

I'm having trouble understanding why the first snippet below executes all five console.log's quickly, while the second snippet executes the console.log's one second apart.
I understand that a closure (aka a function + the scope in which it was declared) is needed to "close" over the value of i at various points in the for loop.
I understand that in the first snippet, the innermost function is immediately invoked, while the second snippet's innermost function is not immediately invoked.
And yet, it does not feel clear to me what is actually happening.
Some questions:
In the first snippet, is the innermost function executing over separate ticks?
In the first snippet, why does the innermost function execute so quickly?
In the second snippet, why does the innermost function execute over one second intervals?
for (var i = 1; i <= 5; i++) {
setTimeout(
(function (x) {
(function () {
console.log(x)
})(i)
})(i),
i * 1000
)
}
for (var i = 1; i <= 5; i++) {
setTimeout(
(function (x) {
return (function () {
console.log(x)
})
})(i),
i * 1000
)
}
Note: I do understand that using let makes this much easier, but I'm trying to understand this in terms of closures.
for (let i = 1; i <= 5; i++) {
setTimeout(
function () {
console.log(i)
},
i * 1000
)
}

This has nothing to do with the mechanics of closures. This is 100% caused by how functions work.
Now, let's tease apart the two different functions. For clarity I'm going to completely remove the for loop:
1:
var i = 1; // We simply hardcode `i` for this demo.
function a (x) {
(function(){
console.log(x);
})(i); // immediately call this function
// THIS IS THE MOST IMPORTANT PART OF THE CODE
// Yes, this space with no code at all at the end of
// this function is the MOST IMPORTANT part of the code.
// This absence of code represents "return undefined".
// All functions that return nothing returns undefined.
}
setTimeout(a(i),i * 1000);
Note: remember that a() returns undefined. So the setTimeout is actually:
setTimeout(undefined,1000);
"Helpfully", if you pass undefined to setTimeout it will gracefully accept it and not generate any errors.
It should also be obvious that you directly call console.log when calling a().
Now let's look at the other code:
2:
var i = 1;
function b (x) {
return (function () {
console.log(x)
}) // <--- note you are not calling the inner function at all
}
setTimeout(b(i), i * 1000);
Note that since b() returns a function setTimeout will call the function returned by b() (the one that calls console.log) after 1 second.

The difference here is less about how closures work and more about how setTimeoute() works. setTimeout will invoke the passed in function sometime after the time passed in. So you pass it a function:
setTimeout(someFunction, 1000)
And in a 1000 milliseconds or so it executes someFunction()
In the first example you are executing the functions before setTimout ever has a chance to by immediately calling someFunction(). By the time setTimeout gets around to it, it doesn't have a function to call -- just the return values of the function you already called. The functions are being called synchronously on the current tick.
You can think of it like passing a callback. If you pass a callback to a function like this someFunction(null, cb) it can execute it later with cb(), but if you pass someFunction(null, cb()) it will receive the return value of cb rather than cb itself. If that's a function it will call that.
In the second example you immediately execute the outside function, but return a function the setTimeout can call later. That is what it does, which is why this works as expected.

It is simple, but tricky :)
In first example, your creating and executing anonymous functions. Then you return undefined to the setTimeout. setTimeout will execute nothing. Thats why it executes quickly.
In second example, your creating and executing an anonymous function that creates another anonymous function and return it to setTimeout. Then setTimeout will execute it.
See my comments:
for (var i = 1; i <= 5; i++) {
setTimeout(
(function (x) {
(function () {
console.log(x)
})(i) -> create and EXECUTE anonymous function (execute it right away)
})(i), -> create and execute anonymous function. returns undefined
i * 1000
)
}
for (var i = 1; i <= 5; i++) {
setTimeout(
(function (x) {
return (function () {
console.log(x)
})
})(i), -> create and execute anonymous function. returns a new function
i * 1000
)
}

Related

How setTimeout works?

I have a concern with setTimeout function in javascript. when we call setTimeout function without return anything, it is okay for me. like
setTimeout(function() {
console.log("ok function called")
},2000);
here in the above example it just simply call that function after 2000ms,
And if I write this like
setTimeout(function(params) {
console.log("passed value is"+params)
},2000,55);
now it will call this function with 55 as an argument, right?
But problem is that when I call to write this like
setTimeout(function(params) {
console.log("passed value is"+params)
}(55),2000);
here function is calling with 55 as params but it is now waiting for 2000ms
And when I wrote like
setTimeout(function(params) {
console.log("passed value is "+params);
return function(){
console.log(params)
};
}(55),2000);
in this only return function is calling with 2000ms delay, the line console.log("passed value is "+params); is executing instantly
please help me get out of this problem.
One is a function. Another is a function call.
First, let's forget javascript for now. If you know any other programming language, what do you expect the two pieces of code below to do?
function a () { return 1 }
x = a;
y = a();
What do you expect x to be? 1 or a pointer to function a?
What do you expect y to be? 1 or a pointer to function a?
A function is not a function call. When you call a function it returns a value.
Now let's switch back to javascript. Whenever I get confused by a piece of code, I try to make the syntax simpler so that I can understand what's going on:
setTimeout(function() {console.log("ok function called")}, 2000);
Now, that's a compact piece of code, let's make the syntax simpler. The above code is the same as:
var a = function() {console.log("ok function called")};
setTimeout(a, 2000);
So what does that do? It will call the function a after 2 seconds.
Now let's take a look at:
setTimeout(function() {console.log("ok function called")}(), 2000);
// Note this ----------^^
That's the same as:
var b = function() {console.log("ok function called")}();
setTimeout(b, 2000);
which can further be simplified to:
var a = function() {console.log("ok function called")};
var b = a();
setTimeout(b, 2000);
So I hope you see what you're really passing to setTimeout. You're passing the return value of the function, not the function.
When you write
setTimeout(function (params) { return something; }(55), 2000);
what actually happens is something like this:
var _temp_func = function (params) { return something; };
var _temp = _temp_func(55);
setTimeout(_temp, 2000);
The anonymous function you have as a parameter to setTimeout is evaluated immediately, even before the call to setTimeout itself. In contrast to that, the actual parameter that ends up in _temp here is called with a delay. This is what happens in your last example.
setTimeout takes only function name without parenthesis.
correct syntax : setTimeout(Helloworld) - here you are setting function
incorrect syntax : setTimeout(HelloWorld()) - here you are calling function
or non IIFE function.
It's an IIFE that you are passing hence it is getting called immediately.
setTimeout(function (params) { return something; }(55), 2000);

How the parens work?

I have found a piece of code in my teacher s notes and I do not understand it.
The point is to find the value for "pass" for which the function would return TRUE.
Can you please answer to my questions below(comments), so I can understand how this works?
<script type="text/javascript">
function findPassword(pass)
{
var b = 1337
//How is this function returning "min" (without the parens?)
function add(x){
b += 84
return min
}
//Same question as above...for "mod" - how is this compiling?
function min(x){
b -= 123
return mod
}
function div(x){
b /= 3
return min
}
function mod(x){
b = b+5+(b%3)
return add
}
//what is the purpose of "fn" if it is not used at all?
var fn = function ()
{
b += 34
return div
}
//WHAT is happening here? "() () ()"
(function (){
b /= 3
return mod
})()()()
if(pass == b*b) {
return true;
} else {
alert("Wrong password !")
return false;
}
}
</script>
So looking at this:
(function (){
b /= 3
return mod
})()()()
You have this:
function (){
b /= 3
return mod
}
Which is a function. You wrap it in brackets and then call it with (), this is called a immediately invoked function expression (IIFE).
So what does it return? It returns mod, which is a function, so the next () will call that function.
What does mod return:
function mod(x){
b = b+5+(b%3)
return add
}
It returns the function add, which you invoke again with (). The function add happens to return the function min, but since we have no more (), we don't invoke it, so it's basically thrown away.
Now, none of this is to suggest this is a good way to structure your code, because it isn't.
As for what value will actually make findPassword return true? Well, you could follow what happens to b in each function.
...or, you could just stick a console.log(b); right after the IIFE to see it's value. The value of pass you need will be that number squared.
Just because nobody pointed out what the purpose of the function fn in this example is:
At first sight, it may seem that you've got an anonymous function self executing, and starting a chain of execution by doing so, however, that encapsulated anonymous function, and add, are actually the only functions in the code that don't execute, and that is because the declaration of fn, before it, is missing a semicolon:
var fn = function ()
{
b += 34
return div
} // <- missing semicolon.
// Because of this, the `var` statement doesn't stop in here.
Because of that missing semicolon, the parentheses encapsulating the anonymous function that comes after this function declaration, are actually executing fn, and passing the anonymous function as an argument to it (and fn is doing nothing with that argument). So, in reality, the code looks like this:
var fn = function ()
{
console.log(arguments[0]); // Logs the anonymous function
b += 34
return div
}(function (){
b /= 3
return mod
})()()()
// The parentheses () mean 'execute' this.
// If they are chained, they execute what the previous
// function returned.
// It is possible to do that when, like in this code, the functions
// return a function reference (meaning, the name of a function).
Which is pretty much the same as this:
var fn = function () {
b += 34/= 3
return div
}( /* Executing fn... */ )( /* div */ )( /* min */ )( /* mod */ )
// fn ends up containing a reference to add, because mod returns that,
// but add is never called.
console.log(fn === add); // true
The chain of execution is this:
fn => div => min => mod
So, to arrive at the password, you do:
var b = 1337;
b += 34;
b /= 3;
b -= 123;
b = b + 5 + (b%3);
// b === 340
// password is b^2: 340 * 340 = 115600
Of course, you can also console.log b, but what's the sense of that?
Follow the return statements and you'll see that they are functions, therefore adding () to that return value will evaluate it.
The first set of parens executes the function immediately before it. This returns mod which is a function. It gets executed by the second parens. This (mod) returns add which is, again, a function. So the last set of parens executes add. Which, in the end, returns min.
It's not very clear the way this program is running but it's essentially modifying that one variable and returning more functions to simulate some logic that modifies the variable in different ways depending on how you call the functions.

SetTimeout and recursivity with cucumber

I have a function written in javascript calling itself in a recursive way :
function f(attempt){
if (attempt + 1 <= 10) {
setTimeout(f(attempt + 1),2000);
}
}
f(0);
For an unknown reason the function is effectively called 10 times but without any delay. The setTimeout seems to execute immediately the function f.
However when I do this then everything works fine :
function f(attempt){
if (attempt + 1 < 10) {
setTimeout(function(){f(attempt + 1);},2000);
}}
f(0);
Do you have an explanation ? Is is because this code is written for Cucumber testing ?
You have to pass the function as a parameter to setTimeout, that means no parenthesis at the end of f. What you are doing right now is calling f and passing it's return value to setTimeout. You can pass arguments to f as the third argument of setTimeout. Your call should look like this:
setTimeout(f, 2000, attempt + 1);
setTimeout(f(attempt + 1),2000);
This code above calls setTimeout function and instead of passing a function to call it passes the result of your f() function, it is invoked right on the spot.
setTimeout(function() { f(attempt + 1) },2000);
But in this case you are passing a reference to your function to be invoked in a 2000 seconds, so it does not evaluate the function itself on the spot.
You should write it like this.
This is an alternative way to do the check and have no private vars.
function f(){
if(++attempt<10){// not shure
setTimeout(f,2000);
}
}
var attempt=0;
f();
Demo
http://jsfiddle.net/3nm2Q/

Understanding JavaScript Closures - Freeze variable passed to callback

I do not yet have a basic understanding of JavaScript closures;
I have a question regarding a specific situation that perhaps is also basic and common example:
Count from 1 to 3 in 3 seconds
See JSFiddle here: http://jsfiddle.net/nAh8x/
The code:
var i,
t;
t = 0;
// Case A
for( i=1; i<=3; i++ ) {
setTimeout( function() { log(i); }, t );
t += 1000;
}
// Case B
for( i=1; i<=3; i++ ) {
setTimeout( wrapper(i), t );
t += 1000;
}
function wrapper(i) {
return function() { log(i); };
}
// Log utility function
function log(msg) {
$('#log').append( msg + '<br />' );
}
Case A doesn't work.
It's clear to me why: every time the function inside setTimeout is called and accesses the i variable, its value has already reached 4.
Case B works.
When wrapper(i) is called it returns
function() { log(i); };
and the above return value (a function) is what goes inside setTimeout. What goes inside setTimeout is exactly the same as Case A
But this time, the i variable have been "frozen" with the value at the time of the call.
Why using the wrapper function let the passed value to be frozen?
That's not completely clear to me.
Closure is an environment which is created with variables scope and nested function by calling of outer function,
Every time the wrapper() is called there would created each different environment for below's function
function wrapper(i) {
return function() { log(i); };
}
Here is the i's value would be same as when wrapper() is invoked. Each time the i's value would be private for that particular environment which made by invoking wrapper() outer function.
The wrapper function has it's own i that is locally scoped to it.
This receives the value of the other i at the time wrapper is called.
It might be clearer if you rewrote it as:
function wrapper(notI) {
return function() { log(notI); };
}
The variable i used inside wrapper is the one the has been passed (as a copy) as the formal parameter to wrapper. It's not the same i as the one inside your for loop - you could rename that variable to anything you like and the code would still work.
It's frozen because it has the value it had each time wrapper was originally called.

javascript function vs. ( function() { ... } ());

I have often see expressions such as:
(function () {
var x = 1;
...
}());
How do I interpret it? syntactically, this alone is a anonymous function definition.
function() {
...
}
what the () after that? and why put it in the enclosing ()?
Thanks
Exactly the same, except that it is being invoked immediately after being converted into a function expression.
// v-----first set of parentheses makes the function an expression
(function () {
var x = 1;
...
}());
// ^-----this set is used to invoke the function
Same as if you did:
var myfunc = function () {
var x = 1;
...
};
myfunc();
or (similar) this:
var returnValue = function () {
var x = 1;
...
}();
Get rid of the names, move the parentheses around, and you can see they're not that different.
The area where I most often find this useful is in callback functions. This notation can also used in cases where you need to include a variable in a callback function, but you need the variable state to not be affected by what goes on outside the function.
var someVal = 1;
setTimeout( (function(one) {
return function() {
alert(one); // alerts a 1 even 10 seconds after someVal++;
}
})(someVal), 10000);
someVal++; // the value in the setTimeout will remain the same as it is locked inside.
In this context, setTimeout takes a function that takes no arguments. So the question of how to pass in a value to that function is answered by creating a function that takes one argument that returns a function that takes 0 arguments.
I suggest anyone wanting to learn more about the power of this notation to play around with it in the Firebug JavaScript console. Once you wrap your head around this concept, you'll start to see areas where this powerful concept can be used.

Categories

Resources