Trying to read this wonderful book of effective javascript(but I am still novice)..
In item 13, it talks about immediately invoked function expression to create local scopes.
I unfortunately however cannot wrap my head around below example
function wrapElements(a) {
var result = [], i, n;
for ( i = 0, n = a.length; i < n; i++ ) {
result[i] = function() { return a[i]; };
}
return result;
}
var wrapped = wrapElements([10,20,30,40,50]);
var f = wrapped[0];
f(); // undefined....
I really try to read that page many times but I still don't understand
Especially below statement from the book.
The bug in the program comes from the fact that the programmer apparently expected the function to store the value of i at the time of the nested function was created. But in fact, it contains a reference to i. Since the value of i changes after each function is created, the inner functions end up seeing the final value of i. This is the key point about the closures.
Closures store their outer variable by reference, not by value.
I honestly think I understand closure storing info by reference and not by value but I honestly cannot relate them to above paragraphs.
Can someone please explain this to me in easier terms or point me to article which does this? I was not able to find any that was easy to understand.
Thank you for your time in advance!!
Let me see if I can help you understand a little. The concept of Immediately-Invoked Function Expressions or (the popular term back when I learned them) Self-Executing Anonymous Functions can be a difficult one to grasp and I recommend that you have a solid knowledge of JavaScript before really digging in, but I may be able to help explain it to you in a way that will help you understand.
So - let's start by examining a normal function declaration that can be done one of two ways:
function someFunction (param1, param2) {
//do stuff
};
OR
var someFunction = function (param1, param2) {
//do stuff
};
And to invoke this function, you would call it like so:
someFunction("param1value", "param2value");
Which is great and works exactly how it's supposed to. But what if you need a function that executes or invokes immediately when it's ran, and don't want to add an object to the global namespace? Here's the real benefit of an IIFE (SEAF). Here is the basic structure of an anonymous function:
(function () {
})();
The first set of parenthesis after (function () { pass parameters into the scope of the function. The second set of parenthesis })(); are used to invoke the function and pass parameters into the function. Wrapping the function declaration in parenthesis makes the function anonymous and allows it to execute or invoke immediately.
Let's take a very basic beginning framework example and explain in a little more detail:
(function (window, undefined) {
})(window);
I remember when I first saw this, I couldn't figure what was going on here and what the point was... This function accepts two parameters to pass into the scope of the function, a window object and an undefined object. (function (window, undefined) { Then when we call it, we pass in only one window object (the global window scope). })(window); To help you understand, this would be like writing a function and executing it like this:
function doStuff (window, undefined) {
//do stuff here
};
doStuff(window);
So why don't people just write their code this way instead of worrying about these IIFE's? Well, writing your functions this way, could clog up your global scope, meaning that now you have a doStuff() object defined that is available across the scope of your entire project. If you have a really large project or framework, you typically only want to expose one object to the global scope, and keep everything else anonymous so it doesn't overwrite or get overwritten by additional code that may also be included in the application.
This is really the basics, but to help you understand the syntax a little more, let me do a real basic working example for you, just to help you wrap your head around the concept. In this example, as soon as the code runs, we're just going to multiply two numbers, whichever two numbers you pass into the function. Then we're going to output the result to a text box with the id "result". You can play around with it here: http://jsfiddle.net/k7f4n0mk/
(function (number1, number2) {
document.getElementById("result").value = (number1 * number2);
})(5, 10);
If we were to write this without an IIFE, you would first have to define the function, then invoke it and it would look like this:
function multiply(number1, number2) {
document.getElementById("result").value = (number1 * number2);
};
multiply(5, 10);
You can see this example here: http://jsfiddle.net/k7f4n0mk/1/
Both examples produce the exact same result, and I'm assuming that you're fairly comfortable with the second one since it's one of the very basics of the language, so why should you worry about this whole new way to write a function if you're old way works just fine? Well, again, this goes back to keeping the global scope clean, and protecting the local scope.
Everyone is pretty familiar with the jQuery javascript library. The entire context of jQuery is wrapped in an IIFE and only the jQuery and the alias $ object are exposed to the global scope - that's pretty impressive for everything that jQuery does. Well, if jQuery didn't have this IIFE syntax, then every function that they declared would be available to the global scope and could easily be overwritten by an unknowing user. They could overwrite any of the function that jQuery uses and completely break the library - so we want to protect all of the functions that jQuery uses (local scope) and keep the global scope clean by only exposing the necessary objects (jQuery and $).
I know this has been a really long answer, but I hope that I have been able to help you gain a little more understanding on this subject. Let me know if you have any other questions.
-EDIT-
To the point of your question - let me see if I can help explain in greater detail.
Here is the code that you are using:
function wrapElements(a) {
var result = [], i, n;
for (i = 0, n = a.length; i < n; i++) {
result[i] = function () { return a[i]; };
}
return result;
}
var wrapped = wrapElements([10, 20, 30, 40, 50]);
var f = wrapped[0];
f();
Now, when you call var wrapped = wrapElements([10, 20, 30, 40, 50]);
wrapped is now referencing an array of functions, because that's what you're returning in your for loop:
wrapped = [function () { return a[i]; },function () { return a[i]; },function () { return a[i]; },function () { return a[i]; },function () { return a[i]; }]
Then, when you call var f = wrapped[0], f becomes a reference to the first function in the array
f = function () { return a[i]; }
So, what you are doing in this code, is adding a new function to the array in your loop. If you try to call the function, a and i will be undefined which is why you are receiving an undefined error.
To achieve the desired results, the code would look like this:
function wrapElements(a) {
var result = [], i, n;
for (i = 0, n = a.length; i < n; i++) {
result[i] = a[i];
}
return result;
}
var wrapped = wrapElements([10, 20, 30, 40, 50]);
var f = wrapped[0];
I hope this helps your understanding a little more. Please let me know if you need any further assistance.
This is a very common bug. Let me simplify it for you.
The following program should alert 1, 2 and 3:
for (var i = 1; i <= 3; i++) {
setTimeout(function () {
alert(i);
}, 10);
}
However, as you can see it alerts 4 3 times instead. What's happening is that by the time the function given to setTimeout is called the value of i has changed. That's the same problem that you are facing.
To solve this problem we make use of immediately invoked function expressions (IIFEs).
for (var i = 1; i <=3; i++) {
(function (new_i) {
setTimeout(function () {
alert(new_i);
}, 10);
}(i));
}
By using an IIFE we're creating a new variable called i whose value is the that of the old i. Now when the old i changes, the new i remains the same. Hence we get the expected result.
A better way to write this would be to use the with statement to create a new i as follows:
for (var i = 1; i <= 3; i++) {
with ({ new_i: i }) {
setTimeout(function () {
alert(new_i);
}, 10);
}
}
Using with is better than the IIFE for 2 reasons:
It's cleaner and easier to read and understand.
It's faster because no function is being invoked. Function invocation is slow.
Hope that helps.
Related
I'm learning JavaScript with Manning's book, Get Programming with JavaScript (by John Larsen). In chapter 11, Listing 11.8, the code:
var getCounter = function () {
var counter = 0;
var countUpBy1 = function () {
counter = counter + 1;
return counter;
};
return countUpBy1;
};
var count = getCounter();
And I'm using jsbin.com to experiment and learn. In the console:
Q1) why calling count(), the result is not always 1? Why is it, counter is set to 0 at the start, before countUpBy1, shouldn't counter inside countUpBy1 also be 0?
Q2) why calling getCounter() is different from count()? calling count() get me a number (which is what I expect), but calling getCounter() get me:
function () {
counter = counter + 1;
return counter;
}
Thanks for explaining in advance.
4/Nov:
#DavidFleeman: Am I correct in my understand to first question (I read all 3 links, plus JavaScript Closures 101: What is a closure?, I never understood JavaScript closures & JavaScript Closures Explained by Mailing a Package:
(deleted my understanding of stepping through the closure)
12/Nov:
I never understood JavaScript closures
Read this link few more times, and it explained way better than I can.
Why is calling count() not always equal to 1?
These nested methods create a closure where the initialization only happens once, and the nested internal method is returned each time. Please read this link to understand:
https://www.w3schools.com/js/js_function_closures.asp
If you prefer MDN, use below link. However, the above link has example that I believe matches the member's scenario:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
And for even more detail, this seems to be a well thought out explanation:
https://blogs.msdn.microsoft.com/ericlippert/2003/09/17/what-are-closures/
Why does getCounter() return the function object instead of executing the method?
Reading the same link above, you can see how to define getCounter() to do exactly what you are asking it to do. You must define it as a self-invoking function. In your example, it is not defined using the self invoking syntax. See example below if you want to define it to work using getCounter() instead of count().
var getCounter = (function () {
var counter = 0;
var countUpBy1 = function () {
counter = counter + 1;
return counter;
};
return countUpBy1;
})();
getCounter();
Closures in a loop are causing me problems. I think I have to make another function that returns a function to solve the problem, but I can't get it to work with my jQuery code.
Here is the basic problem in a simplified form:
function foo(val) {
alert(val);
}
for (var i = 0; i < 3; i++) {
$('#button'+i).click(function(){
foo(i);
});
}
Naturally clicking on any of the three buttons will give an alert saying 3. The functionality I want is that clicking on button 1 will give an alert saying 1, button 2 will say 2 etc.
How can I make it do that?
See the bind method.
$('#button'+i).bind('click', {button: i}, function(event) {
foo(event.data.button);
});
From the docs:
The optional eventData parameter is
not commonly used. When provided, this
argument allows us to pass additional
information to the handler. One handy
use of this parameter is to work
around issues caused by closures
Try this code:
function foo(val) {
alert(val);
}
var funMaker = function(k) {
return function() {
foo(k);
};
};
for (var i = 0; i < 3; i++) {
$('#button'+i).click(funMaker(i));
}
Some important points here:
JavaScript is function scoped. If you want a new ('deeper') scope, you need to create a function to hold it.
This solution is Javascript specific, it works with or without jQuery.
The solution works because each value of i is copied in a new scope as k, and the function returned from funMaker closes around k (which doesn't change in the loop), not around i (which does).
Your code doesn't work because the function that you pass to click doesn't 'own' the i, it closes over the i of its creator, and that i changes in the loop.
The example could have been written with funMaker inlined, but I usually use such helper functions to make things clearer.
The argument of funMaker is k, but that makes no difference, it could have been i without any problems, since it exists in the scope of the function funMaker.
One of the clearest explanation of the 'Environment' evaluation model is found in 'Structure and Interpretation of Computer Programs', by Sussman & Abelson (http://mitpress.mit.edu/sicp/ full text available online, not an easy read) - see section 3.2. Since JavaScript is really Scheme with C syntax, that explanation is OK.
EDIT: Fixed some punctuation.
#Andy solution is the nicest. But you can also use Javascript scoping to help you save the value in your closure.
You do so by creating a new scope in your loop body by executing an anonymous function.
for (var i = 0; i < 3; i++) {
(function(){
var index = i;
$('#button'+index).click(function(){
foo(index);
});
})();
}
Since the loop body is a new scope at each iteration, the index variable is duplicated with the correct value at each iteration.
Use the .each function from jquery - I guess you a looping through similar elements - so add the click using something like:
$(element).children(class).each(function(i){
$(this).click(function(){
foo(i);
});
});
Not tested but I always use this kind structure where possible.
Or just manufacture a new function, as you describe. It would look like this:
function foo(val) {
return function() {
alert(val);
}
}
for (var i = 0; i < 3; i++) {
$('#button'+i).click(foo(i));
}
I'm pretty sure Mehrdad's solution doesn't work. When you see people copying to a temporary variable, it's usually to save the value of "this" which may be different within an inner child scope.
This code is supposed to pop up an alert with the number of the image when you click it:
for(var i=0; i<10; i++) {
$("#img" + i).click(
function () { alert(i); }
);
}
You can see it not working at http://jsfiddle.net/upFaJ/. I know that this is because all of the click-handler closures are referring to the same object i, so every single handler pops up "10" when it's triggered.
However, when I do this, it works fine:
for(var i=0; i<10; i++) {
(function (i2) {
$("#img" + i2).click(
function () { alert(i2); }
);
})(i);
}
You can see it working at http://jsfiddle.net/v4sSD/.
Why does it work? There's still only one i object in memory, right? Objects are always passed by reference, not copied, so the self-executing function call should make no difference. The output of the two code snippets should be identical. So why is the i object being copied 10 times? Why does it work?
I think it's interesting that this version doesn't work:
for(var i=0; i<10; i++) {
(function () {
$("#img" + i).click(
function () { alert(i); }
);
})();
}
It seems that the passing of the object as a function parameter makes all the difference.
EDIT: OK, so the previous example can be explained by primitives (i) being passed by value to the function call. But what about this example, which uses real objects?
for(var i=0; i<5; i++) {
var toggler = $("<img/>", { "src": "http://www.famfamfam.com/lab/icons/silk/icons/cross.png" });
toggler.click(function () { toggler.attr("src", "http://www.famfamfam.com/lab/icons/silk/icons/tick.png"); });
$("#container").append(toggler);
}
Not working: http://jsfiddle.net/Zpwku/
for(var i=0; i<5; i++) {
var toggler = $("<img/>", { "src": "http://www.famfamfam.com/lab/icons/silk/icons/cross.png" });
(function (t) {
t.click(function () { t.attr("src", "http://www.famfamfam.com/lab/icons/silk/icons/tick.png"); });
$("#container").append(t);
})(toggler);
}
Working: http://jsfiddle.net/YLSn6/
Most of the answers are correct in that passing an object as a function parameter breaks a closure and thus allow us to assign things to functions from within a loop. But I'd like to point out why this is the case, and it's not just a special case for closures.
You see, the way javascript passes parameters to functions is a bit different form other languages. Firstly, it seems to have two ways of doing it depending on weather it's a primitive value or an object. For primitive values it seems to pass by value and for objects it seems to pass by reference.
How javascript passes function arguments
Actually, the real explanation of what javascript does explains both situations, as well as why it breaks closures, using just a single mechanism.
What javascript does is actually it passes parameters by copy of reference. That is to say, it creates another reference to the parameter and passes that new reference into the function.
Pass by value?
Assume that all variables in javascript are references. In other languages, when we say a variable is a reference, we expect it to behave like this:
var i = 1;
function increment (n) { n = n+1 };
increment(i); // we would expect i to be 2 if i is a reference
But in javascript, it's not the case:
console.log(i); // i is still 1
That's a classic pass by value isn't it?
Pass by reference?
But wait, for objects it's a different story:
var o = {a:1,b:2}
function foo (x) {
x.c = 3;
}
foo(o);
If parameters were passed by value we'd expect the o object to be unchanged but:
console.log(o); // outputs {a:1,b:2,c:3}
That's classic pass by reference there. So we have two behaviors depending on weather we're passing a primitive type or an object.
Wait, what?
But wait a second, check this out:
var o = {a:1,b:2,c:3}
function bar (x) {
x = {a:2,b:4,c:6}
}
bar(o);
Now see what happens:
console.log(o); // outputs {a:1,b:2,c:3}
What! That's not passing by reference! The values are unchanged!
Which is why I call it pass by copy of reference. If we think about it this way, everything makes sense. We don't need to think of primitives as having special behavior when passed into a function because objects behave the same way. If we try to modify the object the variable points to then it works like pass by reference but if we try to modify the reference itself then it works like pass by value.
This also explains why closures are broken by passing a variable as a function parameter. Because the function call will create another reference that is not bound by the closure like the original variable.
Epilogue: I lied
One more thing before we end this. I said before that this unifies the behavior of primitive types and objects. Actually no, primitive types are still different:
var i = 1;
function bat (n) { n.hello = 'world' };
bat(i);
console.log(i.hello); // undefined, i is unchanged
I give up. There's no making sense of this. It's just the way it is.
It's because you are calling a function, passing it a value.
for (var i = 0; i < 10; i++) {
alert(i);
}
You expect this to alert different values, right? Because you are passing the current value of i to alert.
function attachClick(val) {
$("#img" + val).click(
function () { alert(val); }
);
}
With this function, you'd expect it to alert whatever val was passed into it, right? That also works when calling it in a loop:
for (var i = 0; i < 10; i++) {
attachClick(i);
}
This:
for (var i = 0; i < 10; i++) {
(function (val) {
$("#img" + val).click(
function () { alert(val); }
);
})(i);
}
is just an inline declaration of the above. You are declaring an anonymous function with the same characteristics as attachClick above and you call it immediately. The act of passing a value through a function parameter breaks any references to the i variable.
upvoted deceze's answer, but thought I'd try a simpler explanation. The reason the closure works is that variables in javascript are function scoped. The closure creates a new scope, and by passing the value of i in as a parameter, you are defining a local variable i in the new scope. without the closure, all of the click handlers you define are in the same scope, using the same i. the reason that your last code snippet doesn't work is because there is no local i, so all click handlers are looking to the nearest parent context with i defined.
I think the other thing that might be confusing you is this comment
Objects are always passed by reference, not copied, so the self-executing function call should make no difference.
this is true for objects, but not primitive values (numbers, for example). This is why a new local i can be defined. To demonstrate, if you did something weird like wrapping the value of i in an array, the closure would not work, because arrays are passed by reference.
// doesn't work
for(var i=[0]; i[0]<10; i[0]++) {
(function (i2) {
$("#img" + i2[0]).click(
function () { alert(i2[0]); }
);
})(i);
}
In the first example, there is only one value of i and it's the one used in the for loop. This, all event handlers will show the value of i when the for loop ends, not the desired value.
In the second example, the value of i at the time the event handler is installed is copied to the i2 function argument and there is a separate copy of that for each invocation of the function and thus for each event handler.
So, this:
(function (i2) {
$("#img" + i2).click(
function () { alert(i2); }
);
})(i);
Creates a new variable i2 that has it's own value for each separate invocation of the function. Because of closures in javascript, each separate copy of i2 is preserved for each separate event handler - thus solving your problem.
In the third example, no new copy of i is made (they all refer to the same i from the for loop) so it works the same as the first example.
Code 1 and Code 3 didn't work because i is a variable and values are changed in each loop. At the end of loop 10 will be assigned to i.
For more clear, take a look at this example,
for(var i=0; i<10; i++) {
}
alert(i)
http://jsfiddle.net/muthkum/t4Ur5/
You can see I put a alert after the loop and it will show show alert box with value 10.
This is what happening to Code 1 and Code 3.
Run the next example:
for(var i=0; i<10; i++) {
$("#img" + i).click(
function () { alert(i); }
);
}
i++;
You'll see that now, 11 is being alerted.
Therefore, you need to avoid the reference to i, by sending it as a function parameter, by it's value. You have already found the solution.
One thing that the other answers didn't mention is why this example that I gave in the question doesn't work:
for(var i=0; i<5; i++) {
var toggler = $("<img/>", { "src": "http://www.famfamfam.com/lab/icons/silk/icons/cross.png" });
toggler.click(function () { toggler.attr("src", "http://www.famfamfam.com/lab/icons/silk/icons/tick.png"); });
$("#container").append(toggler);
}
Coming back to the question months later with a better understanding of JavaScript, the reason it doesn't work can be understood as follows:
The var toggler declaration is hoisted to the top of the function call. All references to toggler are to the same actual identifier.
The closure referenced in the anonymous function is the same (not a shallow copy) of the one containing toggler, which is being updated for each iteration of the loop.
#2 is quite surprising. This alerts "5" for example:
var o;
setTimeout(function () { o = {value: 5}; }, 100);
setTimeout(function () { alert(o.value) }, 1000);
I have read a interested blog where this above technique is applied, i understand it will run the function itself. but what's the purpose assign to a variable, when i try to console.log the variable i get undefiend.
var test1 = (function(){
console.log('yay')
})();
console.log(test1)
what's the differnet doing this way below
(function test1(){
console.log('yay');
})();
Suggestion are appreciated. :)
The immediately invoked function expression (IIFE) in Javascript serves to introduce a closure via a new scope. This is often done to compensate for the lack of block scoping in Javascript or provide information hiding a la module pattern (seen often in jQuery plugins).
Minimal example below:
var counter = (function() {
var i = 0;
function inc() {
i++;
return i;
}
return inc;
})();
The return exposes assigns the function inc to the variable counter. Successive invocations of counter() will result in 1, 2, etc. while keeping i hidden.
This is roughly equivalent to an object oriented approach that declared i as private.
In your sample above the function is void which makes no sense to assign the function result to a variable since it is returning nothing:
However tweaking your sample a little bit:
var test1 = (function(){
console.log('yay'); return "hello";
})();
then it makes sense since test1 will return "hello".
So in your original sample there are not differences and the fact that you assign a the result of a function which is not returning values is a bit odd.
Today I came a cross the self executing functions, than somehow I ended up knowing about
Self-Executing Anonymous Functions, then I've read this article: http://briancrescimanno.com/how-self-executing-anonymous-functions-work/
The thing is that I don't know WHY to use Self-Executing Anonymous Functions because if I need to do something like:
var test = "a";
(function(foo) {
alert(foo);
})(test);
I could just make something like:
var test = "a";
alert(foo);
Or did I miss anything?
also this can be done to any code inside the function, but I used alert() to make simple
Update:
Even thought I've already accepted and answer I would like to share something I've found, if anyone came across this question later :)
Using this notation we can also make an endless loop like following:
(function loop(){
// do something here
loop();
)();
There are a couple of reasons why one would use an IIFE:
1) No littering
var a = 'foo';
alert(a);
vs
(function() {
var a = 'foo';
alert(a);
}())
Both examples do the same thing, but in the second example there is no a variable inside the outer scope.
2) State capturing
var a = 'foo';
window.setTimeout(function() { alert(a); }, 1);
a = 'bar';
vs
var a = 'foo';
window.setTimeout( (function(a_copy) {
return function() { alert(a_copy); }
}(a)), 1);
a = 'bar';
The first example alerts bar, while the second alerts foo. You will find this technique used especially with loops.
Your initial example isn't worth to be executed in an anonymous function, so its a bad example to understand WHY to use this technique. Here is a good example to explore state capturing:
var list = [{id: 1, data: null}, ...];
for (var i = 0; i < list.length; i++) {
(function(item) {
// start async request, for each item in the list, in the order of the list
asyncAjax("get-data-from-somewhere.json?what=" + list[i].id, function (response) {
// thats the on success callback, which gets executed when the server responded
// each item will have different response times, therefore the order of response is various
// if we would use simply list[i].data, it wouldn't work correctly, because "i" would has the value of list.length, because the iteration has been finished yet.
item.data = response;
});
})(list[i]); // the function will preserve the reference to the list item inside, until the function has been fully executed
}
When writing sync. code, you can always fallback to classic object oriented style of structering your code. So you can avoid closures / instant-anonymous function calls. But as soon as you use async. mechanics, closures get very handy and make your code looking more clean, off course only if you can read and understand closures :)
By the way, you could also simply write:
function(private) {}(outer)
is the same as
(function(private) {})(outer)
but the second is better, because its simply more obvious for the reader.
The syntax you describe is commonly referred to as an "immediately invoked function expression", or IIFE.
One of the common use cases is to emulate private variables:
var ns = (function () {
var x = 1; // "private"
return {
getX: function () {
return x;
}
}
}());
ns.getX(); // 1
ns.x; // undefined because x is "private"
In that example the x variable is local to the IIFE. It's not directly accessible outside of it. However, since it is referred to by the getX method, which is accessible outside of the IIFE (because it's part of the returned object) a reference to x is kept alive. This is what is usually meant by the term "closure".
Self executing functions are not really useful if you just do an alert inside.
Consider something like this:
(function(foo) {
var a = ..
// do something with a and foo
})(test);
The advantage here is that a is "private" inside the method and cannot be used outside the method. So a doesn't end up as a global variable and can't be overwritten by some other piece of javascript which uses a variable of the same name.