Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialLeon Segal
14,754 PointsWhy does the inner function have to be assigned to a variable?
I don't get why it isn't possible to call dogHouse() in the console. If you do, you get function() returned - which is the inner function called showDogs.
But if you assign the inner function to another variable, in this case getDogs, when you call that variable, the inner function works ok, but all getDogs is doing is calling dogHouse too!!
Why don't they both do the same thing??
Thanks
6 Answers
Sun-Li Beatteay
10,606 PointsSo I did some experimenting and it IS possible to call the function dogHouse in the console. However, the way you do it is:
dogHouse()()
What I'm guessing is that when you call
dogHouse()
in the console, it only runs the outer function dogHouse(), which just returns the inner function to us (in this case being the showDogs inner function). If you watch the video carefully, even when Andrew assigns dogHouse() to getDogs
getDogs = dogHouse();
You still can't use getDogs to call the function in the console, it returns the same answer as dogHouse() does; it just shows you the inner function. To actually call the inner function and run it, you have to use getDogs(). And if we think about it, getDogs = dogHouse() -- so getDogs() = dogHouse()(). The double parentheses tell the console to run the inner function instead of the outer function. Since the inner function is the function that actually logs the value, you will see the console.log function run.
By this logic, if you do something like this:
function dogHouse() {
var dogs = 8;
function showDogs () {
function showMoreDogs () {
console.log(dogs);
return;
}
return showMoreDogs;
}
return showDogs;
}
var getDogs = dogHouse();
You will need to write getDogs()() or dogHouse()()() to run the innermost function and retrieve the value 8 in the console. And I just tried it myself and that's exactly what you have to do.
I hope that helps clear some things up for you.
Daniel Jeffery
Courses Plus Student 1,291 PointsWho let the dogs out, who, who, who!
Joshua Britton
10,252 PointsJust to supplement the info presented in the video, FreeCodeCamp has an excellent article on closures:
Let's Learn JavaScript Closures
Jason Gresalfi
2,269 PointsGregory Ledger : I think your count
variable is never getting past 1 because each time you call the outer()()
function, it's not storing the returned value to anything. When you execute the named function expression counter
it's creating another closure by storing the returned value in memory via the variable assignment, even though the actual value of the counter variable is the function.
Again, I think that's what is going on, it seems like it anyway. If anyone else can shed more light on this, it would be appreciated.
Gustavo Florez
14,811 PointsLet's run dogHouse() in the console. What we get is as expected, it is the function showDogs, since this is declared in the return statement.
ƒ showDogs() {
console.log(dogs);
console.log(birds);
}
So we just saw that calling dogHouse() will give us the function showDogs(). Which logically leads to the conclusion that if we want to execute showDogs() all we need to do is assign dogHouse() to a variable and that variable will become the function that dogHouse() is returning to us. I know this might sound a bit weird, but if you really think about it logically it makes total sense.
var getDogs = dogHouse(); // getDogs "becomes" the function returned by the function call of
// dogHouse(), which is the function showDogs();
Aakash Srivastav
Full Stack JavaScript Techdegree Student 11,638 PointsHey Leon Segal , that's not the necessary condition .
Yes , agreed Chavah Jacobs . You need to call the outer() within a variable to create a closure.
But it can be done through self invoking function too . I have explained that in my last example here.
First let's see , why we need to assign the inner function within a variable -
When you call the outer function own its own , then no closure gets created.
Also , most of the time "closure" is used the increment a counter variable to have track of it .
You can increment the counter only by calling the outer function within a variable and then calling that variable.
In this case , we are saving the returned function in a variable and then calling that returned function as many times as you want , the value get incremented every time.
var countBirds = function() {
var count = 0;
return function(){
count++;
console.log(count + ' birds');
}
};
var foo = countBirds(); // foo is now a closure
foo(); // 1 birds
foo(); // 2 birds
foo(); // 3 birds
foo(); // 4 birds
foo(); // 5 birds
foo(); // 6 birds
Here's is the example where we have call the outer function i,e countBirds function own its own and you can see , the counter doesn't get incremented because , when you are calling the function first time by writing countBirds() , it initializes a new variable , set it to 0 and then return the inner function . Be careful , counter has not been incremented yet. At this stage if you want to see the content of countBirds() , here we have --
console.log(countBirds()); // ƒ (){ count++; console.log(count + ' birds');
}
When you call it again by writing countBirds()() , it will run that returned function and will first increment the counter and the output the value 1.
The same phenomenon is happening in all the three steps where we have called the countBirds function - counter get reassigned to 0 , then increment to 1 and then logging out. We are not saving the returned function any where in this case .
var countBirds = function() {
var count = 0;
return function(){
count++;
console.log(count + ' birds');
}
};
countBirds()(); // 1 birds
countBirds()(); // 1 birds
countBirds()(); // 1 birds
Although , there is a way , if you don't want to use another variable and want to increment the counter just by calling the outer function i,e countBirds on its own , use **self invoking function
A self-invoking expression is invoked (started) automatically, without being called.
Remember only Function expressions can be made "self-invoking" , not Function declaration.
Function expressions will execute automatically if the expression is followed by ().
You have to add parentheses around the function to indicate that it is a function expression.
So let's try it:
var countBirds = (function() {
var count = 0;
return function(){
count++;
console.log(count + ' birds');
}
})();
countBirds(); // 1 birds
countBirds(); // 2 birds
countBirds(); // 3 birds
So , it works :) . You can try either appraach whichever suits you . Happy Coding :)
Thank You
Daniel Salvatori
2,658 PointsThank you for this explanation Aakash, very helpful!
Chavah Jacobs
12,333 PointsI think, based on the video and the MDN article on Closures, that a closure is in some ways a container. The container is created when the function is called within a specific Lexical Environment (which consists of the variable being called).
So if you call outer() within the variable of counter1, this is creating a closure (container) holding that specific value.
But if you called outer() on its own, without a lexical environment, then no closure (container) is created.
When you call outer() again, this is a totally new instance, and thus the counter starts at 0 again.
This is essentially what was said above by Jason Gresalfi.
Leon Segal
14,754 PointsLeon Segal
14,754 PointsSo...getDogs becomes the return of dogHouse() which is showDogs, which is then run by doing getDogs()!
If you just did showDogs(), it wouldn't work because it is hidden.
I get it now - cool!
Thanks!
Gregory Ledger
6,116 PointsGregory Ledger
6,116 PointsStrange. I used the basic structure of a closure
calling counter1() worked, but calling outer()() just returned "called 1 times" no matter how many times I called it. Wondering what is different from doing this than the above 'dogHouse()()"?