Transcript from the "IIFE Pattern" Lesson
>> Kyle Simpson: There is, however, a downside to this approach. To create a function like this which was a declaration, we had to give it a name. In this case bob, and that name was included in the enclosing scope, the very same scope that we were trying not to pollute or collide with.
[00:00:17] So now we have another race condition between us deciding on a name that somebody else won't try to collide with. We need that name because we need it on line 7 to invoke the function. Does everybody follow this reasoning? The good part is that we have a function, but the bad part is oops, we've got a name that's polluting things.
[00:00:35] How do we square these two problems? How do we create a scope but not pollute a name? There was a hint given earlier when we talked about function expressions. Remember what happens to the name of a function expression. So what I wanna observe first is line 7 is really two separate operations.
[00:00:53] You recall earlier in the course when we were talking about the way a line 7 would execute is it's first got to resolve the bob expression. Look up whatever value is in it, which in this case happens to be a reference to a function, and then it executes it with a parenthesis on line 7.
[00:01:11] So let's think about it as literally two separate operations. I just put some parenthesis there to emphasize the idea that the bob expression gets evaluated first and then we call the function. If that's the case, if we can think of that as an expression, what if we just took the function bob and put it in place of the variable in that expression on line 7?
[00:01:34] What if we literally just made this from a function declaration into a function expression? All I've done is take that function declaration bob and put it in place of the bob named expression. Now, something subtle but important has happened because it's no longer a function declaration anymore. It's just a function expression.
[00:01:55] Why? Cuz the word function is not literally the first thing in the statement. So it's a function expression, which means that name bob is not gonna pollute the outer enclosing scope anymore. Now all of a sudden, that function expression is just gonna sit there, until on line 6, we have that second set of parentheses that executes it.
[00:02:18] This pattern has a name, it's called an IIFE. It stands for Immediately Invoked Function Expression. That parenthesis set there immediately invokes the function expression that we give prior in the statement. If you'd like to read more about where that name comes from, this blog post, I think it's widely regarded to Ben Alman, real big in the jQuery crew.
[00:02:41] I think he still works for a consultancy out of Boston [COUGH] in Bocoup. He's widely regarded as coming up with the name for immediately invoked function expression. We needed some name for this pattern. We didn't have a good name, so we're a creative bunch. We just named it the IIFE.
[00:03:12] We want that function to exist only for the purpose of scope and so we really just need it to run once and be done. That's exactly what the IIFE does for us, okay?
>> Kyle Simpson: Some examples of how people use IIFEs. And by the way, I always like to name my IIFEs, exactly for the same reason that we talked about naming function expressions.
[00:03:36] You should name your IIFEs. And if you can't come up with some other good name, at least use the name IIFE, okay? But usually, there's some better name to refer to that particular block of scope, and that's especially true if it's an entire file. If the IIFE is wrapped around the whole contents of a file, which is how it's most commonly used, you can think about what the contents of that file is doing.
[00:03:57] Maybe those represent the customer login utilities in your application. Well, call your IIFE customer login utilities, or something like that. Give it a name that's more self descriptive, it'll show up in the stack traces, etc, etc.
>> Kyle Simpson: But what's interesting to me about IIFEs is that they really are just regular function calls, which means we can actually sort of import identifiers from the enclosing scope.
[00:04:23] Here I'm passing in the foo and I'm giving it a different name. That actually allows me to alias or to rename things to be more convenient to me. So one of the ways that I like to do this when I wrap an IIFE around the contents of, say, a file, I'll pass in the window object, but I'll give it the name global.
[00:04:40] So the argument will be window down on line 6, but the parameter name up on line 3, I'll call it global. That way, any place that I need to say global dot in front of something, that's a super glaring obvious neon sign that says, this thing is on the global.
[00:04:55] I just think the word global is better than the word window. Another place where this is often used is with jQuery for example, or other frameworks that like that dollar sign variable name. It's a nice short variable name but lots of people wanna use it so that creates collision if you are using more than one of those utilities.
[00:05:12] And how many of us love writing j capital Q query throughout all of our code? That's a terrible variable name. So what you can do is pass in the jQuery object or whatever framework of your choice, and call it dollar sign. That way, within the context of your IIFE, it will always predictably be that dollar sign points at the thing you wanted it to point at.
[00:05:32] So it's nice and useful for us to control our lexical main spaces through the arguments and parameters to our IIFEs. Questions about the IIFE pattern?
>> Kyle Simpson: I mentioned that using the IIFE pattern can also be useful inside of loops. This is a big hint to something we'll be dealing with a little bit later in the course.
[00:06:03] Here I wanted to create a block of scope inside of my for loop. Why? Because I wanted a different j for each iteration. So I made an IIFE inside of the loop and then I've put a var j declaration there, and that j is gonna get recreated for each run of the for loop.
[00:06:22] That'll actually turn out to be really useful when we talk about closure later. So we can put these IIFEs literally in any place that we could put a statement if we wanna create some scope there. It's not as nice and clean as, say a block, and we'll get to block scoping in just a moment, but it is the standard by which we've created these blocks of scope as we just make these IIFEs.
>> Speaker 2: So, I have a question. Does the compiler actually create a variable for the IIFE? Or how does that work? Or just in the run time?
[00:07:12] So it would run across this function. It would see that there was a name identifier there. It would need to step into that scope. It would need to create a bucket. It's called a lexical environment. But it would need to create a bucket like a blue bucket, and the var j would be a blue marble that was stuck in it.
[00:07:44] So there's always a reality difference. There's always a difference between what we theoretically say happens conceptually and what physically happens. And I can't tell you what physically happens cuz I'm not a browser developer. I don't know what they actually do. But conceptually, this runs through exactly the same process as any other function.
>> Speaker 2: So in this case, will there be five buckets for the IIFE?
>> Kyle Simpson: Again, conceptually we're gonna be recreating a new bucket each time we loop, all right? But practically speaking, the engine might be able to figure out, you're gonna reuse the scope in each loop, maybe I'll just create one, or maybe I don't even need an environment.
[00:08:22] I don't know how they actually do it. That's an implementation question that would be best passed along to an engine developer. But conceptually, this would be five separate buckets. We really should keep our attention on the concept rather than getting too worried about the implementation cuz Firefox may do it differently than Chrome, who does it differently than Edge.
[00:08:44] Who knows, right? We should focus on the concept and the concept is we get a separate variable, and we do that when we want a separate variable. If I didn't have the IIFE there, if I just said var j on line 2, how many js would there be?
>> Kyle Simpson: Just one, right? Because that compiles and we'd find the var j, we'd attach it to the enclosing function scope, which would have been in this case the global scope, right? There's only gonna be one of those js. Let's say we're in a situation where we want a j for each loop.
[00:09:15] This is how we have to do it. Make sense? So think about the conceptual requirements of your code and less about the nitty gritty of how an engine might influence it.