I heard that every function remembers(?) the lexical environment where the function had created.
In this code, The function function () { console.log(i);},
I want to know where this function had been created. If some function is a parameter of other function, where is the created(?)/generated point?
function countSeconds(howMany) {
for (var i =1; i <= howMany; i++) {
setTimeout(function () {
console.log(i);
}, i * 1000 );
}
};
In this code, The function function () { console.log(i);}, I want to know where this function had been created.
This function is defined as a function expression. Such an expression is evaluated at runtime, much like an expression { y: x*x } would be evaluated at runtime. But in this case the evaluation result is a function object. And that function is then passed as argument to setTimeout. This means there are just as many functions created as there are iterations of your for loop.
Now, even though the function expression is evaluated at the moment setTimeout is executed, this does not mean that the body of the function is executed at that same time. It is not. It will only be executed when the timeout expires. At that time the function body executes, and at that time only it will evaluate expressions used in that code, such as variable i. In your example, the variable i will already have reached the value howMany+1, because that for loop already ran to completion before the timer expired, and the callback got called.
If that is something you want to avoid, then use a separate variable i for each iteration of the for loop. With let instead of var you create such distinct variables, which only live inside the for loop's block. And so then each of the function expressions will reference its "own" i:
function countSeconds(howMany) {
for (let i =1; i <= howMany; i++) {
setTimeout(function () {
console.log(i);
}, i * 1000 );
}
};
countSeconds(10);
If some function is a parameter of other function, where is the created(?)/generated point?
Like all arguments to a function call, they're evaluated right before the function is called. You can rewrite this with two temporary variables into the equivalent
function countSeconds(howMany) {
for (var i=1; i<=howMany; i++) {
const __arg1 = function() {
console.log(i);
};
const __arg2 = i * 1000;
setTimeout(__arg1, __arg2);
}
}
The function is created when the function expression is evaluated.
(Also notice that this code has the famous closure in a loop problem.)
I dont understand what you mean?
You mean where the function console.log() ist defined?
class console {
log(text) {
[I dont know]
}
}
Then you can make "console.log()" to call the function "Log" from Claas console? Did you mean that?
Related
Can someone explain to me why JSLint complains about "Function inside the loop" with this example:
for (var i = 0; i < buttons.length; i++) {
(function(i) {
buttons[i].onclick = function(e) {
t.progressBars[t.current].update(buttons[i].getAttribute("data-value"));
}
})(i);
}
But dosen't when I change it to:
function makeHandler(i)
{
return function() {
t.progressBars[t.current].update(buttons[i].getAttribute("data-value"));
}
}
for (var i = 0; i < buttons.length; i++) {
buttons[i].onclick = makeHandler(i);
}
I don't quite understand as it seems that with each loop iteration new function object has to be returned, even though it happens inside of makeHandler() function. Why the second example is ok with JS linters?
Quoting from linterrors,
var elems = document.getElementsByClassName("myClass"), i;
for (i = 0; i < elems.length; i++) {
(function (iCopy) {
"use strict";
elems[i].addEventListener("click", function () {
this.innerHTML = iCopy;
});
}(i));
}
What we have now captures the value of i at each iteration of the loop. This happens because JavaScript passes arguments to functions by value. This means that iCopy within the capturing function is not related to i in any way (except for the fact that they happen to have the same value at that point in time). If i changes later (which it does - on the next iteration of the loop) then iCopy is not affected.
This will work as we expect it to but the problem now is that the JavaScript interpreter will create an instance of the capturing function per loop iteration. It has to do this because it doesn't know if the function object will be modified elsewhere. Since functions are standard JavaScript objects, they can have properties like any other object, which could be changed in the loop. Thus by creating the function in the loop context, you cause the interpreter to create multiple function instances, which can cause unexpected behavior and performance problems. To fix the issue, we need to move the function out of the loop:
I would have liked to use Array.prototype.forEach here, like this
buttons.forEach(function(curButton) {
curButton.onclick = function(e) {
t.progressBars[t.current].update(curButton.getAttribute("data-value"));
};
});
Your two examples are not equivalent.
In the first, you are creating an anonymous function and calling it on every loop.
The inner function (the click event handler) is fine - you're assigning a new function - but it's the anonymous outer function that is inefficient in this context. In your second example the outer function is refactored out of the loop where is it only created once, instead of buttons.length times.
i have a simple function called Range that creates an array of integers based on start, step and end value...
function Range (start, end, step) {
// default step is 1..
if (step === undefined ) step = 1;
// creating an array...
var arr = [], index = 0;
while(start <= end) {
arr[index] = start ;
index += 1;
start += step;
}
// simple function expressions
var getAll = function () {
return arr ;
};
var getOne = function(n) {
return arr[n] ;
};
// returns a unnamed function ..
return function(i) {
if (i === undefined) { return getAll() ;}
else {return getOne(i); }
}; // not an iife
}
so basically Range is a function which returns a unnamed function which again returns a named function expression declared in the function Range.. err.. i dont know.. something like that...
now the below code...
var first10 = Range (1,10) ; // no new ..() here, so no instance should be created.. only Range is called..
var first10Odd = Range(1,20,2) ; // and Range is called again..
alert(first10); // alerts - function(i) { ... }
alert(first10Odd); // alerts- function(i) { ... }
alert(first10()) ; // alerts - 1,2,3,...10
alert(first10Odd()); // alerts - 1,3,5,...19
alert(first10(0)); // alerts - 1
alert(first10Odd(9)); // alerts- 19
why do the alerts alert as specified in the comments??... i think Range is a just a function and not a object constructor and also no instance was created... shouldn't the local variables of function be destroyed as soon as the function is completed??
or is my logic wrong?? what is going on in the above code?? can anyone please explain....
i have made a fiddle of my code here..
sorry for asking this stupid question..
Welcome to the land of closures in Javascript. They can be very powerful and extremely useful once you understand them. But, if your prior experience is with languages that do not have them, they can feel a bit foreign at first.
Some answers/explanation:
Calling Range(x, y) returns a function that can then be called later.
Because that function that is returned is inside another function scope that has variables, a closure is created.
That closure stays alive (even though the outer function has finished executing) because there is a lasting reference to the inner function saved in your variables and that inner function has a reference to the local variables in the outer function. These references keep the closure from being garbage collected (so it stays alive).
That inner function can then reference the variables in the outer function, including the arguments originally passed to it.
This construct allows you to create these custom functions that have arguments pre-built into them.
The notion of this type of closure only exists in some languages. It does not exist in C++, for example.
When the function returned by calling Range(x,y) is itself executed later, it can use any of the variables that were originally in scope to it.
Each call to Range(x,y) causes a new closure to be created.
getAll and getOne are local variables in the outer function that are assigned a function. They access other local variables in the outer function. All of these are in the previously mentioned closure that is created each time Range() is called.
There is lots written about what a closure is (which you can Google and read), but I like to think of it as an execution context that contains everything that was in scope at the time a function is called (including all variables). Each time a function is called, such an execution context it created. Since everything in javascript is garbage collected and will only be freed/destroyed when there are no references left to it, this is true for this execution context too (e.g. closure). As long as something has a reference to it or something in it, then the execution context will stay alive and can be used by any code that might run into that execution context.
Line by line annotation:
// first10 is assigned the anonymous function that the call to Range()
// returned. That anonymous function has access to the original arguments
// passed to the Range(1,10) call and other local variables in that function.
var first10 = Range (1,10) ; // no new ..() here, so no instance should be created.. only Range is called..
// same as the call before, except this also includes the step argument
var first10Odd = Range(1,20,2) ; // and Range is called again..
// this makes sense because Range(1,10) returns a function so
// when you alert it's value, it tells you it's a function
alert(first10); // alerts - function(i) { ... }
alert(first10Odd); // alerts- function(i) { ... }
// When you execute the function in first10, it runs that function
// and the alert shows the return value from that function
// This particular function is set to return the entire array if nothing is passed
// to it
alert(first10()) ; // alerts - 1,2,3,...10
alert(first10Odd()); // alerts - 1,3,5,...19
// This particular function is set to return a specific index from the array
// if an argument is passed to it
alert(first10(0)); // alerts - 1
alert(first10Odd(9)); // alerts- 19
If you know how to use the javascript debugger, you can set a breakpoint on this line if (i === undefined) { return getAll() ;} in the inner function and you will be able to inspect all the variables that are in scope, including start, end and step from the outer function.
You may find this article useful reading as it encapsulates some of the ways that closures can be used with object declarations: http://javascript.crockford.com/private.html (not exactly what is being done here, but might help you understand them).
Welcome to javascript closures. Lets take line by line.
var first10 = Range(1,10);
var first10Odd = Range(1,20,2);
We know that Range is just a function. So, in these two lines we are just calling Range function with 2 and 3 arguments respectively.
Now, what happens when you call a function. The obvious answer is, the body of the function gets executed. What do we have in the body of the function.
if (step === undefined ) step = 1;
var arr = [], index = 0;
while(start <= end) {
arr[index] = start ;
index += 1;
start += step;
}
I hope that the above seen lines are pretty obvious and you don't have any problems with them.
var getAll = function () {
return arr;
};
What does this line do? It creates a function at run time. Why runtime? Lets see an example.
<script>
func1();
var func1 = function() {
alert("Hi");
}
</script>
<script>
func1();
function func1() {
alert("Hi");
}
</script>
If you use the first script block, it will throw error. Why? You are calling a function which hasn't been defined yet. The second case, you are defining the function during javascript parsing time itself. The type of function which was created in the first case is called anonymous function. Let us get back to getAll. Now we know that getAll is simply a variable which points to an anonymous function, lets look at what it does. It returns arr. How does it have access to arr? It is declared outside the function and so it still has access to it. Same case with
var getOne = function(n) {
return arr[n] ;
};
Now the very important part,
return function(i) {
if (i === undefined) {
return getAll();
} else {
return getOne(i);
}
};
What does it do? It returns a function. To be precise, it returns an anonymous function. Whenever Range is called, it creates a new anonymous function, which accepts one parameter and returns it. So, now what do first10 and first10Odd have? Yes. You are right, they have functions. I hope that explains
alert(first10); // alerts - function(i) { ... }
alert(first10Odd); // alerts - function(i) { ... }
Let us examine both the functions. When first10 is called with nothing, I mean, first10(), the parameter i takes the value undefined. So, we are actually making a call to the anonymous function with no parameters and it is supposed to return getAll(). If you remember, first10 was created with Range(1,10);. So, the arr will now have [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].
You might ask, when we return from the function, wont the variables declared inside the function go out of scope. The answer is Yes and No. Yes, when you simply return a value. No, when you return a function. When you return a function, the state of the variables will be maintained. This property is called closures. That is why it returns
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] for alert(first10())
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19] for alert(first10Odd())
1 for alert(first10(0))
19 for alert(first10Odd(9))
Please read more about Closure here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures
I'll get to the point: I have this loop:
for (var i = 1; i <= toSchedule; i++) {
when = trackWrapper.lastPlay +
(trackDuration +
(looper.timeInterval - trackDuration));
track.play(true, when);
trackWrapper.lastPlay = when;
}
The play method has this inside the body:
[...]
// Here when is a different value for each call (verified)
// Many calls of the play method are performed before the returned function below is run as a callback
function playingCallback(myWhen){
return function(buffers){
// Here myWhen will always be equal to the value of the last call occurred BEFORE the first callback execution
console.log("myWhen = "+myWhen);
[...]
};
};
var realCallback = playingCallback(when);
track.scheduled.push(when);
track.recorder.getBuffer(realCallback);
So, for example:
play(true, 1);
play(true, 2);
play(true, 3);
// Wait for it...
myWhen = 3;
myWhen = 3;
myWhen = 3;
Now: I've read about closures, I've read about the "infamous loop problem", I've read tens of answers here on StackOverflow but I couldn't figure this out. It's the second time I have this kind of problem with callbacks so, at this point, I guess I haven't completely understood what is going on.
Could you please explain to me what is supposed to be wrong with the code above? Thank you in advance.
Generally you should understand the following rule: A clousure will have access to its "surrounding scope", even after the scope has been exited. But it will be the state of the scope at execution time and not(!) at creation time of the closure
If you create a closure inside a loop, it will have access to the loop variable. But the loop will most likely already have ended. So the loop variable will hold the value of its last loop.
So if your closure is a callback you should create a copy of your relevant scope variable(s) at creation time and use this copy at execution time. You can do this (for example) by creating an inner closure from an immediately executing anonymous function
function myOuterScope(count) {
for(i=0; i<count; i++) {
setTimeout((function(local_i) {
// this function will be immediately executed. local_i is a copy of i at creation time
return function() {
// this is the function that will be called as a callback to setTimeout
// use local_i here, and it will be 0, 1, 2 instead of 3, 3, 3
}
})(i)
, 1000);
}
}
myOuterScope(3);
I am trying to undrstand the code
for(var i = 0; i < 10; i++) {
setTimeout((function(e) {
return function() {
console.log(e);
}
})(i), 1000)
}
from here http://bonsaiden.github.com/JavaScript-Garden/#function.closures
I understood this method :
for(var i = 0; i < 10; i++) {
(function(e) {
setTimeout(function() {
console.log(e);
}, 1000);
})(i);
}
Can anyone please help me by explaining the first one?
I will try to explain how I understands the first one,
first i is 0,
setTimeout is called,
self calling function "function(e)" is called with i=0,
Im stuck!! what happens when this function returns a function?
All the first one does is return a function that will be called after the timeout happens.
The purpose of it is to create a sub-scope for each iteration of the for loop so that the incrementing i isn't overridden with each iteration.
More explanation:
Lets take this apart into two different pieces:
for(var i = 0; i < 10; i++) {
setTimeout((function(e) {
return function() {
console.log(e);
}
})(i), 1000)
}
This is the first piece:
for(var i = 0; i < 10; i++) {
setTimeout(function(){
console.log(i); //9-9
},1000);
}
Now, when you run this loop, you will always get console.log()'s that contain 9 instead of 0 to 9. This is because each setTimeout is using the same reference to i.
If you wrap the setTimeout part of that in an anonymous function, it creates a scope for each iteration allowing each setTimeout to have it's own i value.
for(var i = 0; i < 10; i++) {
setTimeout((function(i) {
return function() {
console.log(i); // 0-9
}
})(i), 1000)
}
The outer function inside the setTimeout gets executed immediately with an i of 0 for first iteration, 1 for second, etc. That function then in turn returns a function which is the function that setTimeout uses. A function is being generated and returned for each iteration of the loop using a different value for i.
Both end up with the same result: a setTimeout is called with a function to invoke, which writes a number from 0 to 9 on the console. Both use nested functions to get the current value of i into a closure so you don't end up logging 10 9's.
The first code chooses to have a function returning the function that setTimeout will call. The second changes the nesting order so that the closed-over function invokes setTimeout itself. The net effect is the same.
Other than stylistic reasons and personal choice, I don't see a reason to choose one over the other.
"Can you please check the updated question specifying where im getting confused"
OK, here's the long explanation. Remember that the first parameter to setTimeout() needs to be a reference to the function that you want executed after the specified delay. The simplest case is to just name a function defined elsewhere:
function someFunc() {
console.log("In someFunc");
}
setTimeout(someFunc, 100);
Note there are no parentheses on someFunc when passing it as a parameter to setTimeout because a reference to the function itself is required. Contrast with:
setTimeout(someFunc(), 100); // won't work for someFunc() as defined above
With parenthese it calls someFunc() and passes its return value to setTimeout. But my definition of someFunc() above doesn't explictly return a value, so it implicitly returns undefined - which is like saying setTimeout(undefined, 100).
But it would work if changed someFunc() to return a function instead of returning undefined:
function someFunc() {
return function() {
console.log("In the function returned from someFunc");
};
}
So now (at last) we come to the code from your question:
setTimeout((function(e) {
return function() {
console.log(e);
}
})(i), 1000)
Instead of referencing a function by name and calling it as someFunc(i) it defines an anonymous function and calls it immediately as (function(e) {})(i). That anonymous function returns another function and it is that returned function that becomes the actual parameter to setTimeout(). When the time is up it is that returned function that will be executed. Because the (inner) function being returned is defined in the scope of the (outer) anonymous function it has access to the e parameter.
I am looking at a javascript code that manipulates an HTML A tag , and I'm having trouble understanding how it sets up the "onclick" property. It seems to be telling it to update ytplayer_playitem with the index variable j and then call ytplayer_playlazy(1000)
But what's up with all the parentheses? What details in the javascript syntax allows it to be setup like this?
var a = document.createElement("a");
a.href = "#ytplayer";
a.onclick = (function (j) {
return function () {
ytplayer_playitem = j;
ytplayer_playlazy(1000);
};
})(i);
Well, basically, the value of onclick is a function that will get called when the element is clicked. Whatever you want to happen when the user clicks the element goes in the body of the function.
You could create a named function and then assign it to the element's onclick attribute:
function youClickedMe() {
...
}
a.onclick = youClickedMe
but that clutters up the namespace with a function name that is never referenced anywhere else. It's cleaner to create an anonymous function right where you need it. Normally, that would look like this:
a.onclick = function() { ... }
But if we try that with your specific example:
a.onclick = function() {
ytplayer_playitem = something; // ??
ytplayer_playlazy(1000);
}
We see that it hard-codes the something that gets played. I'm assuming the original code was taken from a loop which generates several clickable links to play; with the code just above, all of those links would play the same thing, which is probably not what you want.
So far, so straightforward, but this next leap is where it gets tricky. The solution seems obvious: if you're in a loop, why not just use the loop variable inside the function body?
// THIS DOESN'T WORK
a.onclick = function() {
ytplayer_playitem = i;
ytplayer_playlazy(1000);
}
That looks like it should work, but unfortunately the i inside the function refers to the value of the variable i when the function is called, not when it's created. By the time the user clicks on the link, the loop that created all the links will be done and i will have its final value - probably either the last item in the list or one greater than that item's index, depending on how the loop is written. Whatever its value is, you once again have the situation where all links play the same item.
The solution in your code gets a little meta, by using a function whose return value is another function. If you pass the loop control variable to the generating function as an argument, the new function it creates can reference that parameter and always get the value that was originally passed in, no matter what has happened to the value of the outer argument variable since:
function generate_onclick(j) {
// no matter when the returned function is called, its "j" will be
// the value passed into this call of "generate_onclick"
return function() { ytplayer_playitem = j; ytplayer_playlazy(1000); }
}
To use that, call it inside the loop like this:
a.onclick = generate_onclick(i);
Each generated function gets its very own j variable, which keeps its value forever instead of changing when i does. So each link plays the right thing; mission accomplished!
That's exactly what your posted original code is doing, with one small difference: just like the first step in my explanation, the author chose to use an anonymous function instead of defining a named one. The other difference here is that they are also calling that anonymous function immediately after defining it. This code:
a.onclick = (function (j) { ... })(i)
is the anonymous version of this code:
function gen(j) { ... }
a.onclick = gen(i)
The extra parens around the anonymous version are needed because of JavaScript's semicolon-insertion rules; function (y) {...}(blah) compiles as a standalone function definition followed by a standalone expression in parentheses, rather than a function call.
"But what's up with all the parentheses? "
Most of the parentheses are just doing what you'd expect.
There's an extra set that isn't technically needed, but is often used as a hint that the function is being invoked.
// v-v---these are part of the function definition like normal
a.onclick = (function (j) {
// ^-----------this and...v
return function () {
ytplayer_playitem = j;
ytplayer_playlazy(1000);
};
// v---...this are technically not needed here, but are used as a hint
})(i);
// ^-^---these invoked the function like normal
"What details in the javascript syntax allows it to be setup like this?"
The upshot is that the function is invoked immediately, and passed i so that its value is referenced by the j parameter in the immediately invoked function.
This creates a variable scope that the returned function will continue to have access to. This way it always has access to the j variable, and not the i that gets overwritten in the loop.
These inlined functions are abused a bit IMO. It becomes clearer if you simply make it a named function.
for(var i = 0; i < 10; i++) {
// create the new element
a.onclick = createHandler(i);
// append it somewhere
}
function createHandler (j) {
return function () {
ytplayer_playitem = j;
ytplayer_playlazy(1000);
};
}
The resulting handler is exactly the same, but the code is much less cryptic.
Right, I'm going to guess that the surrounding code looks like this:
for (var i = 0; i < playitems.length; i++) {
// above code here
}
Now, you could do the obvious thing here, and assign the onclick property like this:
a.onclick = function() {
ytplayer_playitem = i;
ytplayer_playlazy(1000);
};
However that wouldn't work very well, because the value of i changes. Whichever link was clicked, the last one would be the one activated, because the value of i at that point would be the last one in the list.
So you need to prevent this happening. You need to do this by creating a new scope, which is done by creating an extra function, which is immediately invoked:
(function (j) {
// some code here
})(i);
Because i has been passed into the function, the value is passed rather than a reference to the variable being kept. This means that you can now define a function which will have a reference to the correct value. So you get your extra function to return the click handling function:
a.onclick = (function (j) { // j is the right number and always will be
return function () { // this function is the click handler
ytplayer_playitem = j;
ytplayer_playlazy(1000);
};
})(i);
So each a element has its own click handler function, each of which has its own individual j variable, which is the correct number. So the links, when clicked, will perform the function you want them to.
a.onclick = (function (j) {
return function () {
ytplayer_playitem = j;
ytplayer_playlazy(1000);
};
})(i);
This creates a "closure" to ensure that the value of i that is bound to the handler is the value of i "at that time" and not i in the general.
In your code, the function inside the () is an expression, executed and passed the variable i. This is the (i) you see in the end part. In this executed function expression, the i becomes the local variable j. This executed function expression returns the handler function that is to be bound the onclick event carrying the value of j which was i "at that time"
if i did not use the closure:
//suppose i is 1
var i = 1;
a.onclick = function () {
ytplayer_playitem = i;
ytplayer_playlazy(1000);
};
//and changed i
i = 2;
//if you clicked the <a>, it would not be 1 onclick but 2 because you
//did not assign the value of i "at that time". i is "tangible" this way
a.onclick = (function (j) {
return function () {
ytplayer_playitem = j;
ytplayer_playlazy(1000);
};
})(i);
What you have here is a self-invoking anonymous function. Let's break it down, first replacing the body of the function with something simpler (return j + 1;):
function( j ) { return j + 1; }
This s a run-of-the-mill anonymous function or closure. This line of code is an expression, and so it has a value, and that value is a function. Now we could do this:
var foo = function( j ) { return j + 1; }
foo( 5 ); // => 6
You recognize this, I'm sure—we're assigning the anonymous function to the variable foo, and then calling the function by name with the argument i. But, instead of creating a new variable, because the closure is an expression we can call it like this instead:
( function( j ) { return j + 1; } )( 5 ); // => 6
Same result. Now, it's just returning j + 1 but in your code it returns something else: Another anonymous function:
return function() { /* ... */ }
What happens when we have a self-invoking anonymous function that returns a function? The result is the "inner" function that was returned:
a.onclick = ( function( j ) {
return function() {
ytplayer_playitem = j;
ytplayer_playlazy( 1000 );
}
}
)( i );
If i was equal to 9 then a.onclick would now hold a function equivalent to this:
function() {
ytplayer_playitem = 9;
ytplayer_playlazy( 1000 );
}
As others have pointed out, the usefulness of this is that when ( function( j ) { /* ... */ } )( i ) is invoked you are capturing the value of i at that time and putting it into j rather than creating a reference to the value i holds, which may (and probably will) change later on.