Immediately Invoked Function Expressions (IIFE)

This is a companion discussion topic for the original entry at http://www.kirupa.com/html5/immediately_invoked_function_expressions_iife.htm

This is true of the function itself, but there can be many traces (good and bad/accidental) that the function has run. The most accidental way is if you forget to declare a variable and use it. This will be detected as an error if you opt-in to ES5’s strict mode:

(function(){ 'use strict'; foo = 5 })() // Uncaught ReferenceError: foo is not defined

If you aren’t using strict mode, which is the default, you will have just set the global variable foo in your program.

Plus, you can still mess with any global program state, even in strict mode, as long as those objects aren’t frozen:

(function(){ 'use strict'; Math.PIE = 3 })()
Math.PIE // 3

So, as the tutorial mentions, IIFEs are great for protecting the IIFE code from the rest of your (or others’) programs, but they don’t stop your IIFE code from wreaking havoc on the code outside of your IIFE.


There are ways other than using wrapping parentheses to reach a valid point in the grammar so that your function is treated as an expression. Pretty much any unary operator will work, for example:

void function(e){ console.log(e) }('hi')
!function(e){ console.log(e) }('hi')
typeof function(e){ console.log(e) }('hi')

I forget if there’s any good reason why people have settled on the paren syntax, other than that it reminds people of Lisp, I guess. :stuck_out_tongue:

That’s a great point about IIFEs having the ability to wreck things outside of their bubbles. I’ll modify the tutorial by adding a note summarizing what you mention.

Regarding the syntax, the paren version does look at lot like Lisp haha!

Void… Cooool. Looks like the return type :stuck_out_tongue_winking_eye:

2 Likes

Hello, please make sure that what you write about is actually true and tested.

I have tried running this code in multiple enviroments (browser console, jscomplete-com, jsfiddle-net and playcode-io) :

function quotatious(names) {
    let quotes = [];
    
    for (let i = 0; i < names.length; i++) {   
        
        let theFunction = function() {
            return "My name is " + names[i] + "!";
        }
        
        quotes.push(theFunction);
    }
    return quotes;
}

// our list of names
let people = ["Tony Stark", "John Rambo", "James Bond", "Rick James"];

// getting an array of functions
let peopleFunctions = quotatious(people);

// get the first function
let person = peopleFunctions[0];

// execute the first function
alert(person());

And it runs just fine with “Tony Stark” being shown in the alert popup.

@richtone This is a consequence of updating the site’s code samples to use more modern JavaScript, namely switching over from var to let. There is, however, a difference of behavior between these two types of declarations, one of which breaks this example. So by blinding making that replacement, this example no longer shows the broken behavior. If you change the lets to vars, you should see what was reportedly to be expected (specifically for the for).

@kirupa I want to think I remember this coming up for the book too, but I don’t remember what we did. Used var in this case? Removed this example?

Apologies @richtone. As @senocular mentions, this is an oversight from me doing a find/replace of vars into lets. I’m going to revise this tutorial to go back to using var with a note that none of this works when using let.

@senocular - the entire chapter was :scissors:

1 Like