Emma Tech

  • Emma Home
  • Emma Blog
  • Job Openings
  • RSS

Using IIFEs in JavaScript to control variable scope

Because creating too many global variables is iffy

Josh Mock 11 Oct 2011 javascript 11 Comments

On a recent project, a few of us have been chal­lenged to take our JavaScript skills to a new level. We’ve even learned a few new tricks from a group of out­side devel­op­ers that we’re work­ing with who spe­cial­ize in JavaScript.

One such trick is using immediately-invoked func­tion expres­sions (IIFEs), which are often used to take advan­tage of JavaScript’s scope rules to fun­nel in cer­tain global vari­ables and avoid cre­at­ing too many of your own globals.

The basic con­cept of an IIFE (lov­ingly pro­nounced “iffy,” occa­sion­ally referred to as a self-executing or self-invoked anony­mous func­tion) is to wrap a por­tion of JavaScript in an anony­mous func­tion that gets called immediately:

(function () {
     // your code here
})();

Wrapping the func­tion in paren­the­ses turns it into an expres­sion rather than a dec­la­ra­tion. The empty set of paren­the­ses that fol­lows tells the inter­preter to run that expres­sion as a func­tion. It is a more com­pact and anony­mous equiv­a­lent to the following:

var foo = (function () {
     // your code here
});
foo();

Take con­trol of your globals

Writing code like this might seem redun­dant until you give it more sub­stance, of course. Let’s use an exam­ple I recently came across in a web­site I was work­ing on at home.

This web­site, unfor­tu­nately, has depen­den­cies on both the jQuery and Prototype libraries. Both libraries use $ as a global vari­able; Prototype as a short­ened way to access document.getElementById(), and jQuery for, well, pretty much every­thing it does. Because of this, the value of $ changes depend­ing on which library is included last. In this case, Prototype was the last-included library, so $ belongs to Prototype.

Now if I want to use jQuery’s func­tions, instead of using $( ... ), I have to use jQuery( ... ). This is a lit­tle annoy­ing, what with jQuery being the more widely-used library that more devel­op­ers are famil­iar with. To fix this, I wrapped my code in an IIFE and passed it the jQuery global variable:

(function ($) {
     $(document).ready(function () {
          // my code
     });
})(jQuery);

This means that, no mat­ter what the global vari­able $ means out­side my IIFE, within it I’m explic­itly telling it to run jQuery func­tions. I could just as eas­ily assign jQuery to any other unused vari­able and it would have the same effect:

(function (p) {
     p(document).ready(function () {
          // my code
     });
})(jQuery);

Keep your vari­ables to yourself

Aside from fun­nel­ing in global vari­ables to what­ever val­ues I want, I can also use IIFEs to pre­vent vari­ables from being added to the global scope.

For exam­ple, you might run the fol­low­ing code on a web page out­side of any function:

var x = "hello";
alert(x); // alert dialog with the text "hello"

By doing this, x is now a global vari­able. If x was assigned else­where before this script was called, it’s now reas­signed to the value "hello". Not always ideal. To avoid this with­out hav­ing to name and call a new func­tion, wrap your code in an IIFE. This keeps your vari­ables within a smaller scope and still runs the lines immediately:

(function() {
     var x = "hello";
     alert(x); // alert dialog with the text "hello"
})();

Now, x is only assigned to the value "hello" for the dura­tion of the IIFE. If x was assigned glob­ally before the IIFE, it would keep that value after the IIFE runs:

var x = "foo";

(function() {
     var x = "hello";
     alert(x); // alert dialog with the text "hello"
})();

alert(x); // alert dialog with the text "foo"

As you’ve seen, the IIFE con­ven­tion can be a great stan­dard prac­tice when writ­ing your own libraries and plu­g­ins, when extend­ing JavaScript where you may not be aware of every con­text in which cer­tain vari­able names are used and to pre­vent too much data from creep­ing its way into the global scope.

11 comments

Trey Piepmeier commented:

2011-10-20, 10:42

Thanks, Josh!

Even though I was in the train­ing with you, it really helps to have it sum­ma­rized like this.

Aaron commented:

2012-03-21, 12:14

Great info, thank you! This will be espe­cially use­ful when past­ing in other people’s jQuery code (and they all use $) rather than using jquery or .noCon­flict( ) and find/replace like I’ve been doing. No good bur­ri­tos in Nashville though?

Josh Mock

Josh Mock commented:

2012-03-21, 12:18

Aaron, I’ve since found a decent bur­rito or two in Nashville. But noth­ing will beat what you can get in California!

Glad I could help give some clar­ity on your jQuery scop­ing issues.

Jeremy G commented:

2012-07-02, 23:03

Great usage tuto­r­ial!
I will point out how­ever, for script kid­dies like myself who like to copy and paste, that you for­got the ter­mi­nat­ing curly bracket for your IIFE in the exam­ples where you enclosed the $/jQuery global vari­able (which are the 3rd and 4th code entries).

Line 5 should end })(jQuery); instead of )(jQuery);

Or are there browsers that parse the JS just fine that way?

Josh Mock

Josh Mock commented:

2012-07-12, 08:16

Nice catch, Jeremy! I don’t think JS parsers would like that, actu­ally. I’ve updated the code sam­ples accordingly.

azopco commented:

2013-02-02, 00:30

What about set­ting global vars from within the IIFE?

azopco commented:

2013-02-10, 13:52

Hello,

Why my last com­ment isn’t get­ting posted? My ques­tion still remain: how to access/set global vars from within the IIFE???

Thank you…

Josh Mock

Josh Mock commented:

2013-02-11, 09:52

Sorry azopco! We got your com­ment but it got stuck in spam moderation.

To set global vari­ables from inside an IIFE, assign val­ues to window.yourVariableName. This only works in JavaScript you run in your browser, as the global “win­dow” vari­able is not avail­able in Node.js.

azopco commented:

2013-02-14, 08:10

Thank you Josh for your reply!

There is another thing I dis­cov­ered about IIFES is that we can pass more than one variable:

var some­thin­gElse = ‘dada’;
(func­tion ($, smthin­gElse) {
console.log(smthingElse);
})(jQuery, somethingElse);

// out­put “dada” in the console

azopco commented:

2013-02-14, 12:54

By the way, the window.varName works for vari­ables, but it doesn’t work for functions :(

window.myFunction(); doesn’t work from within an IIFE, while it works outside.

it’s dif­fi­cult to keep a track of all used func­tions (that are avail­able in the global scope) and pass them to the IIFE.

Any other technique?

azopco commented:

2013-02-14, 13:00

Sorry for the many posts, but update:

Actually window.myFunction() does work but you need to declare your func­tion this way:

myFunc­tion = function() { … }

Which is sim­ply sav­ing the func­tion in a vari­able. Declaring it like this will NOT work:

func­tion myFunction() { … }

Leave a comment

Click here to cancel reply.

About Josh Mock

Josh Mock

Josh is a web developer by day and an amateur DJ and music writer the rest of the time. He recently moved to Nashville from California and is looking for a good burrito.

Read more from Josh

Emma Tech on Twitter

    Follow Emma Tech »
    Help wanted

    • Popular Tags

      Python12 api7 UX5 conferences4 postgres4 workflow4 time4 javascript3 PHP3 jQuery3 tools3 editors2 travel2 server maintenance2 Git2 maintenance windows2 Haml1 Frank1 Ruby1 CSS1 PyCon1 office1 Sass1 downtime1 post‑mortems1 cgit1 books1 Trac1 collaboration1 community1 Twitter1 Facebook1 OAuth1 coding1 cool sites1 Redis1 github1 objects programming refactoring1 integration1 salesforce1 usability testing1 Social Posting1 music1 productivity1 bugs1 TextExpander1 san francisco1 Convore1 Vim1 releases1 legacy data1 HTML1 reading1 Django1 PgCon1 testing1 TDD1

    Emma is a member of the Email Sender & Provider Coalition and the Messaging Anti-Abuse Working Group.

    Copyright © 2003 - 2013 Emma.
    All rights reserved.

    • Get Emma's Newsletter
    • Visit the Emma Blog
    • @emmaemailtech on Twitter
    • @emmaemail on Twitter
    • Emma on Facebook

    Emma's email marketing makes communicating simple and stylish.
    Inquire now for more details.