📒
SDV503
  • SDV503
  • Command Prompt
    • Windows Command Prompt
    • Mac OS Terminal
  • GIT & GITHub
    • GitHub
    • Git
      • Git Workflow
        • Forking Workflow
  • README
    • How to write a readme.md file?
    • Write a better README.me
    • Generate a README for GitHub Repo Quickly
  • Code-comments
    • Clean Comments
    • Writing Comments in a Good way
  • Pair Coding
    • What is Pair Coding?
    • Pair Programming Experience
  • Programming?
    • What is Programming?
    • What Is A Programming Paradigm?
    • JavaScript Programming Paradigms
  • Number Systems
    • Decimal and Binary numbers
  • JavaSCript
    • Introduction To JavaScript
      • The JavaScript Engine
  • JS Call Stack
    • JavaScript call stack
    • JavaScript & Memory
      • Memory Leaks in JavaScript
    • Execution Context and Execution Stack in Javascript
      • Javascript Execution Context and Hoisting
  • JavaScript Variables
    • Introduction to JS Data Types
    • Primitive and Non-Primitive
    • Operator precedence and associativity
      • JS Operators Part One
      • JS Operators Part Two
      • JS Operators Part Three
    • Clean Code for JS Variables
  • JavaScript Scopes
    • Scope (Chain) Visualized
  • Javascript  — this keyword
  • JavaScript Data Types
    • More JavaScript Data Types
  • JavaScript Expressions and Statements
  • if/else, switch and ternary operator
    • If/Else statement
  • Switch Statement
  • Ternary Operator
  • JavaScript Loops
    • Loops in JavaScript
      • Trouble With Loops
  • Objects
    • JavaScript Objects
      • Prototypal Inheritance Visualized
      • JavaScript Number Object
      • JavaScript String Object
  • Functions
    • JavaScript Function Part One
    • JavaScript Function Part Two
    • Immediately Invoked Function Expressions ~ IIFE
    • JS => Arrow Functions
    • JavaScript Callback
    • Hoisting in JavaScript
      • Hoisting Visualized
    • Recursion Functions
    • Curry and Function Composition
  • JavaScript Features
    • JSpread Operator
    • JavaScript Built-in Functions & Objects
  • Data Structures&Algorithms
    • JavaScript’s Data Types
    • Data Structures in JavaScript
      • Introduction to Big O Notation
      • Big O Notation in Javascript
      • Linked Lists
        • Linked Lists — 2
      • Hash Tables
      • Stack & Queue
  • TLDR
    • Single quotes (‘ ’) and double quotes (“ ”) in JavaScript
  • ES6
    • Generators and Iterators
    • Javascript Classes
    • JavaScript closures
    • JavaScript Promises & Async/Await
      • Event Loop Visualized
  • C#
    • What does C#? (C Sharp)
    • C# vs JavaScript
    • What Is The Difference Between C#, .NET, ASP.NET, Microsoft.NET, and Visual Studio?
    • What is the .NET Framework?
    • Methods and Properties of Console Class in C#
    • Datatypes in C#
    • C# Code Comments
    • The if statement
    • The switch statement
    • Loops
    • Comparison operators
    • Addition assignment operators
    • The String Interpolation Operator
    • Arrays
    • Lists
    • Dictionaries
Powered by GitBook
On this page
  • Function Declaration vs Function Expression
  • IFFEs Help to Minimize Naming Collisions
  • Does an IIFE Need Enclosing Parentheses?
  • Alternative Syntax for IFFEs
  • Do IIFEs Have to Be Anonymous?
  • IFFEs and Closures

Was this helpful?

  1. Functions

Immediately Invoked Function Expressions ~ IIFE

An imediately invoked function expression (IFFE), pronounced ‘iffy’, is a JavaScript design pattern often used to minimize naming conflict and create private variables.

The conventional format for an IFFE is to enclose the whole function within the grouping operator (a set of parentheses) and to leave it unnamed (i.e., anonymous). The additional set of parentheses at the end is what immediately invokes it:

(function() {
    // Function contents
})();

Before we get into IFFEs at a more detailed level, let’s review the differences between function declarations and function expressions.

Function Declaration vs Function Expression

A “function declaration” (synonymous with “function statement”) requires the keyword function, a name (i.e., what follows function), and a function body (what’s between the curly braces). When a JavaScript file (or HTML document containing JavaScript) is loaded, function declarations are hoisted (moved) to the top of the code before any code is executed.

function doSomething(){
  // Function contents
};

An “expression” is any valid unit of code that resolves to a value. The main difference between function declarations and function expressions is that when using function expressions, the name can be omitted, creating an anonymous function. Further, function expressions are not hoisted; the they are not loaded until the JavaScript interpreter reaches them in the script. If you try to call a function before that point, you’ll get an error.

The reason you can store an IIFE in a variable (a feature of function expressions in most contexts, one exception being callbacks [when they’re passed as a parameter to another function]) is that function expressions return a value (as all expressions do).

IFFEs Help to Minimize Naming Collisions

It’s widely considered good practice to minimize pollution of the global namespace (having many different named variables and/or functions in the global scope) to reduce the chances of naming collisions.

Defining variables inside functions or between curly braces makes them inaccessible to the global namespace. (In case you need a refresher, var [which it’s better not to use anymore] is function or global scoped, while let and const can be either global [not between curly braces] or block scoped [between curly braces].) Creating private/local scope (making variables, etc., inaccessible in global/public scope) is not a special feature of an IIFE; you could just define the variables inside a regular function as the example below demonstrates (or simply between a set of curly braces if you’re using let or const).

function exampleFunction() {
  let foo = 'bar';  console.log(foo); // Outputs: 'bar'
}exampleFunction();console.log(foo); // ReferenceError: foo is not defined

This being said, with an IIFE, you can use an anonymous function and eliminate the chances of it being returned more than once.

(function() {
  let foo = 'bar';  console.log(foo); // Outputs: 'bar'
})();console.log(foo); // ReferenceError: foo is not defined

You can store the IFFE in a variable, since function expressions evaluate to a (function) value — whereas function declarations, being statements, don’t evaluate to anything.

const result = (function() { 
  const name = 'Natalie'; 
  return name; 
})(); // Console immediately logs output:
result; // "Natalie"

Does an IIFE Need Enclosing Parentheses?

If you assign the IIFE to a variable, the enclosing parentheses can be omitted:

const example = function() {
  alert('IIFE success!');
}();
// Alerts "IIFE success!"

If you don’t assign the IIFE to a variable, surrounding it with parentheses is necessary for it to still work because without them, as soon as the JavaScript interpreter arrives at the function keyword, it will assume it has encountered a function declaration (resulting in an error message that a name is needed) .

function() {
  alert('IIFE success!'); // ...Not
}();
// SyntaxError: function statement requires a name

But, of course, don’t add a name — that would be fulfilling the requirements for the function to be considered a function declaration, but an IIFE requires the function to be an expression (hence the word “expression”!).

If for some reason you don’t want to use enclosing parentheses, you can circumvent the need to use them by preceding the function with an exclamation point, which forces the JavaScript interpreter to treat whatever follows as an expression:

!function() {
  alert('IIFE success!');
}();
// Alerts "IIFE success!"

There are other ways to force the JavaScript engine to interpret a function as a function expression:

~function () { /* ... */ }();
-function () { /* ... */ }();
+function () { /* ... */ }();
void function () { /* ... */ }();

Alternative Syntax for IFFEs

There are two ways to format an IFFE (assuming you’re using enclosing parentheses). You can use either style; it’s a matter of personal preference.

Style 1:

(function() {
    // Function contents
})();

Style 2:

(function() {
   // Function contents
}());

Do IIFEs Have to Be Anonymous?

IFFEs used to be called “self-invoking anonymous functions,” but the name was changed to what they’re now called in part because the word “anonymous” was deceptive. For instance, this is perfectly acceptable:

(function namedIsFine() {
  alert('Named IFFE success!');
})();

IFFEs and Closures

You can also utilize closures inside IFFEs.

Here’s an example of a closure in a regular (non-IFFE) function. (The inner function, as well as the count variable it references, comprise the closure.)

function makeCounter() {
 let count = 0;
 return function() {
   ++count;
   return `count equals ${count}`; 
 };
};// If you just call it two times without storing the result in a variable, count is reset to zero each time
console.log(makeCounter()()); // count equals 1
console.log(makeCounter()()); // count equals 1// Since the counter variable below holds a reference to the result of the outer function's call (which is the inner returned function, which "closes over" count), the JavaScript engine won’t wipe it from memory ("garbage collection")
let counter = makeCounter();console.log(counter()); // count equals 1
console.log(counter()); // count equals 2

Below is a closure in an IFFE.

let countingFunction = (function() {
  let count = 0;
  return function() {
    ++count;
    return `count equals ${count}`; 
  };
})();console.log(countingFunction()); // count equals 1
console.log(countingFunction()); // count equals 2

Both of these examples of closures have the benefit of preserving the value of count in subsequent function calls, whereas if a closure were not used, count would be reset to zero following each function invocation. Further, in both cases the count variable (as any let variable in a block) is private — that is, not globally accessible.

While the closure in the first (non-IFFE function) example can be called to reset the iterator whenever desired, the closure in the IFFE cannot be reset since the whole function is only run once (subsequent calls are to the function within the IFFE).

An advantage of using the IFFE version of the closure over the non-IFFE version is that you don’t have to name it (you just have to assign it to a variable in order to call it again) — or if you do name it, it won’t be visible in the global scope — so there’s one fewer item polluting the global namespace.

Here’s another example of an IIFE containing a closure:

let add = (function() {
 let count = 0;
 return function() {
   return ++count; // Adds 1 to count
 };
 console.log(count);})();add(); // 1
add(); // 2

The variable add stores the result of executing the outer function (the IFFE). It’s only executed that one first time, in which it sets count to zero and returns the function expression within it. It’s important to note the inner function is not run when the IFFE is created; it must be called before the incrementation of count executes and its result is returned.

So, once the IFFE is assigned to add, each time add() is called, the inner function is executed. This increments and returns the updated count variable. The number that appears in the console after running this code is the updated value of count returned by the inner function.

PreviousJavaScript Function Part TwoNextJS => Arrow Functions

Last updated 5 years ago

Was this helpful?

In case you’re unsure what a closure is, defines a closure as “a combination of a function and the lexical environment within which that function was declared.” Lexical environment...? The defines a lexical environment as an “association of Identifiers to specific variables and functions based upon the lexical nesting structure of ECMAScript code.” In other words, a closure is a combination of a function and its reference to its external environment (which allows it to access the contents of that environment).

MDN
ES5 specification