Immediately Invoked Function Expressions (IIFEs)

 

Immediately Invoked Function Expressions (IIFEs)

Immediately Invoked Function Expressions (IIFEs) are a powerful and commonly used feature in JavaScript. They are functions that are executed immediately after they are defined. The primary reason to use an IIFE is to obtain data privacy because any variables declared within the IIFE cannot be accessed by the outside world.

Here's the basic syntax of an IIFE:

(function() {
  // Function logic here
})();

Let's look at some examples:

Example 1: Basic IIFE

(function() {
  var localVar = 'This is a local variable';
  console.log(localVar);  // Output: This is a local variable
})();

In this example, the function is wrapped in parentheses (() => { ... }), followed by () to immediately invoke it.

Example 2: IIFE that stores and displays result

var result = (function() {
  var x = 10;
  var y = 20;
  return x + y;
})();

console.log(result);  // Output: 30

In this example, the IIFE is immediately invoked and returns the sum of x and y. The result of the IIFE, which is 30, is assigned to the variable result.

Example 3: IIFE used to create private variables

var counter = (function() {
  var count = 0;
  return {
    increment: function() { count++; },
    decrement: function() { count--; },
    getCount: function() { return count; }
  };
})();

// Increment the counter
counter.increment();
counter.increment();
counter.increment();
console.log(counter.getCount());  // Output: 3

// Trying to access the private count variable directly
console.log(counter.count);  // Output: undefined (cannot access private variable)

In this example, count is a private variable scoped to the IIFE, inaccessible from outside. The returned object exposes methods (incrementdecrement, and getCount) that allow controlled manipulation and access to the private count variable.

IIFEs are commonly used to:

  • Avoid polluting the global namespace.
  • Create closures in JavaScript.
  • Create private and public variables and methods.
  • Execute async and await functions.
  • Work with require function.
var items =[0,1,2,3,4,5,6,7,8,9];

for(var i=0; i<items.length; i++){

    setTimeout(function(){console.log(items[i])},1000);  // (10) undefined
}

In JavaScript, var is function-scoped, not block-scoped. This means that a new i is not created for each loop iteration. Instead, there's just one i that's shared across all iterations. By the time the setTimeout callbacks start to execute, the loop has already finished, and i is equal to items.length (which is 10). Since there's no item at index 10 in the items array, items[i] is undefined.

To fix this, you can use an Immediately Invoked Function Expression (IIFE) to create a new scope for each iteration of the loop. Here's how you can do it:

var items = [0,1,2,3,4,5,6,7,8,9];

for(var i=0; i<items.length; i++){
  (function(i) {
    setTimeout(function() {
      console.log(items[i]);
    }, 1000 * i);
  })(i);
}

In this corrected version of the program, an IIFE is used to create a new scope for each iteration of the loop. This ensures that each setTimeout callback has its own i, so it logs the correct item to the console. The delay is also multiplied by i to ensure that the items are logged one second apart, in order. The first item is logged immediately, the second item is logged after one second, the third item is logged after two seconds, and so on. This creates a sequence of console logs with a one second delay between each log. Please note that setTimeout is asynchronous, so the rest of your code will continue to execute while the timeouts are waiting to finish. If you have code that needs to run after all the timeouts have finished, you may need to use Promises or async/await.

You can fix the issue by using the let keyword instead of var in your loop. The let keyword in JavaScript declares a block scope local variable, unlike var which declares a variable globally, or locally to an entire function regardless of block scope. Here's how you can do it:

var items = [0,1,2,3,4,5,6,7,8,9];

for(let i=0; i<items.length; i++){
    setTimeout(function(){console.log(items[i])},1000 * i);
}

In this corrected version of the program, let is used instead of var to declare i. This means that a new i is created for each iteration of the loop, so each setTimeout callback has its own i, and it logs the correct item to the console. The delay is also multiplied by i to ensure that the items are logged one second apart, in order. The first item is logged immediately, the second item is logged after one second, the third item is logged after two seconds, and so on. This creates a sequence of console logs with a one second delay between each log. Please note that setTimeout is asynchronous, so the rest of your code will continue to execute while the timeouts are waiting to finish. If you have code that needs to run after all the timeouts have finished, you may need to use Promises or async/await. This solution is simpler and more modern than using an IIFE, and it's generally recommended if you're writing new JavaScript code and don't need to support older browsers that don't understand let. However, please be aware that let is not supported in Internet Explorer. If you need to support Internet Explorer, you should use var and an IIFE.

Vikash Chauhan

C# & .NET experienced Software Engineer with a demonstrated history of working in the computer software industry.

Post a Comment

Previous Post Next Post

Contact Form