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 trialjason chan
31,009 PointsCan someone walk me through this? anonymous called function
//Lamba
var closureAlert = (function() {
var x = 0;
var alerter = function() {
alert(++x);
}
return alerter;
}());
// calling itself with a closure
closureAlert();
closureAlert();
3 Answers
miikis
44,957 PointsThis is possible because functions are first-class citizens in JS which means you can pass 'em around like any other data type. Like this:
var humpty = function() {
return "Do the humpty-hump!";
};
var funky = function(daFunk) {
return daFunk();
};
funky(humpty); // Returns "Do the humpty-hump"
Duh, you're thinking, I knew that already! But, it's bigger than that...you can also have functions that return functions! Like this:
var specialFunk = function() {
var isSmooth = false;
return function(myFunkStyle) {
return "Do the " + myFunkStyle;
}
};
// So then, you're like: "Imma do me a specialFunk()" and you call specialFunk()
specialFunk();
// But that just returns a function
// So you call it again
var funkPocket = specialFunk(); // Remember, specialFunk is being called, but it returns a function
funkPocket("Humpty!"); // This is like calling twice: specialFunk()('Humpty!')
// Woah. Calling funkPocket() returns "Do the Humpty!"
But, whyyyyy? Well, you see that isSmooth variable? It's now a private variable, meaning that, try as you might, you will never, ever know if your funk is smooth, or not, unless you're inside of specialFunk(). Many other languages, like Java, allow you to create a private variable like that sooooo easily. In Java, in fact, it's as simple as: private boolean isSmooth;. But, since JavaScript doesn't have classes like Java, you have to go through this little dance. And what do the locals call this little dance? That's right, closures.
But, sometimes you don't want to put your specialFunk() in your funkPocket(). Sometimes, you just want to call your specialFunk() one time and have everything done for you automagically. Enter: IIFE aka Immediately-Invoked Function Expressions (which, incidentally, is what your code above is doing). Remember, the idea here is to evaluate the first function, your specialFunk(), automatically at runtime. In your code above, you do it by using parentheses but you can actually do it a few different ways. Maybe you've seen code in the wild that has a random semi-colon or exclamation mark before a named function.
;function specialFunk(myFunkStyle) {
}();
// is, effectively, the same as:
var specialFunk = (function(myFunkStyle) {
})();
So, to wrap it all up, here's the final showdown of specialFunk():
var specialFunk = (function() {
var isDamnSmooth = false;
return function(myFunkStyle) {
// Here, you write some code to check if your funk style is acceptable
if(isDamnSmooth) {
return "Do the " + myFunkStyle + "!";
}
return "Uh-uh. Not happening.";
}
})();
specialFunk("Humpty-hump!") // The Humpty is too-cool so this would return: "Do the Humpty-hump!"
So, I wrote this on the fly; it's probably riddled with grammar mistakes and the like. And I highly doubt it's very lucid to the novice JavaScript-er. So if you have specific questions, feel free to ask and I'll try to give clearer, more-specific answers ;)
John Halbert
12,922 PointsOh, man... I'm not sure how many responses you'll get to this one, so I'll have a try at it..
var closureAlert = (function() {
var x = 0; //2. reserve x in memory
var alerter = function() { //3. define alerter as undefined. It will not run yet.
alert(++x);
}
return alerter; //4. Alerter is defined and called at this point, ++x, making x = 1
}()); //1. IIFE, basically meaning this part of code will be directly called first.
closureAlert(); // x = 1
closureAlert(); // x = 2 at this point because the execution context of x inside the closure was previously = 1
I hope that's clear, closures are tricky.
A huge resource when referring to JS' "weird parts" for me has been, oddly enough, "Javascript: The Weird Parts" (Udemy Course Link). Normally I'm not too convinced Udemy courses have much to offer, but this one was absolutely essential for me. It goes over things like this in the Closure section, and really helps explain how they're done.
miikis
44,957 PointsActually, on your number 3, alerter() is not undefined — it's a function. It's that function that gets called at your number 4.
John Halbert
12,922 PointsIsn't the default JavaScript engine behavior to reserve a space in memory with the default value of "undefined" until the code is called (when return alerter is executed?)
miikis
44,957 PointsNot to my knowledge.
You're probably referring to the nuances of hoisting function expressions vs. function declarations. And that gets crazy enough before you even get to the coercion involved in JS primitive data types vs JS objects... and how that translates into memory allocation and garbage collection... ahhhh let's go back to functions.
This is a function expression:
function alerter() {
// alert stuff...
}
These two are both function declarations:
var alerter = function() {
}
var alerter = function anAlertByAnotherName() {
}
The difference is that function expressions get hoisted to the top of the current scope at runtime, so order doesn't matter as much. In other words, this works:
alerter(); // I alerted...
function alerter() {
// alert stuff...
}
alerter(); // I alerted too...
Function declarations, on the other hand, are just normal-ass variables that contain either an anonymous function (a function with an empty name property) or a named function (a function with a ... not-empty name property). These functions are hoisted to the top of the current scope at parse-time, or as soon as the JS engine gets to that containing variable. Like so:
alerter(); // Nope. No such thing yet...
typeof alerter; // returns 'undefined'
var alerter = function() {
};
typeof alerter; // returns 'function'
alerter(); // Now we're talking... um.. alerting...
Incidentally, the reason you'd assign a named function to a variable — as opposed to an anonymous function — is this:
var alerter = function anAlertByAnotherName() {
// You can call anAlertByAnotherName here...
anAlertByAnotherName();
}
// You can call alerter() here...
alerter(); // Alerting, per usual...
// But anAlertByAnotherName() doesn't exist here...
typeof anAlertByAnotherName; // returns 'undefined'
// Actually, though, I'm misleading you
// The use-case here is that you'd have a longer, non-conflicting and more-descriptive handle for your function out here
// But, inside your actual function, you can use a shorter, more-concise handle
// So, I should've made the variable name 'anAlertByAnotherName' and the function name 'alerter'
So... no... function declarations do not evaluate to undefined until they're called ;)
John Halbert
12,922 PointsAppreciate the clarification, thanks Mikis!
miikis
44,957 PointsNo problem, John. Sometimes it helps to write about things you think you know; it provides a little sanity check and helps to cement it all in. For me anyway ;)
Jennifer Nordell
Treehouse TeacherI'll give it a shot! Here goes nothing! If I understand this correctly (and someone please tell me if I'm misunderstanding this) you start by calling the closureAlert. Pretty straight-forward. It starts by then calling a function with x set to an inital value of 0. That function then calls another function alerter which then increments the value of x. So now the value for x is 1. That value is returned to the anonymous function above and then the result is stored in closureAlert. So when you run it again it seems like it would reset x to 0 right? Except that a closures function still has access to the variable's parent scope even AFTER the function has closed. I don't know if any of this made sense, but that's how I understand it.
Jennifer Nordell
Treehouse TeacherJennifer Nordell
Treehouse TeacherMikis Woodwinter I think that may be the best description I've ever read of function declarations vs. function expressions. Kudos!
miikis
44,957 Pointsmiikis
44,957 PointsThanks Jennifer! Glad you got something out of it :)