5.5 Immediately Invoked Function Expressions
We’ve covered quite a few concepts on functions so far. The last concept that I would like to cover is the concept of IIFE (pronounced as iffy), which stands for Immediately Invoked Function Expressions.
As the name suggests, these are functions that are invoked immediately once the browser reaches them.
Recall that previously when we declare our functions, we need to call the function to invoke it? For instance, if we have
function simpleFunc() {
console.log("Just a simple function");
}
we need to write
simpleFunc();
to call the function.
With IIFE, we do not need to call the function; it’ll be invoked immediately. To do that, we simply need to enclose the function expression in parenthesis and add a second pair of parenthesis to invoke the function immediately. Let’s look at an example. First, add two pairs of parenthesis to chap5.js as shown below:
()();
The first pair of parenthesis is for enclosing the function expression. The second pair is to call the function.
Copy the code for simpleFunc() into the first pair of parenthesis as shown below:
(function simpleFunc() { console.log("Just a simple function"); })();
When we use IFFEs, we do not need a name for the function. You can delete the name simpleFunc from the code above.
Now refresh template.html. You’ll get the following output:
Just a simple function
One of the main reasons for using an IIFE is to prevent naming conflicts. In cases where we link more than one Javascript file within the same HTML page, it is possible that we may have two or more global variables with the same name. This can happen when you have different programmers working on each Javascript file. To prevent that from happening, we can change each file to an IIFE by enclosing the entire code in parenthesis followed by another pair of parenthesis to invoke it.
Let’s consider an example:
For this, we need to first create the four files below:
- IIFE.html
- main.js
- script1.js
- script2.js
Next, add the following code to IIFE.html.
<script type="text/javascript" src="main.js"></script> <script type="text/javascript" src="script1.js"></script> <script type="text/javascript" src="script2.js"></script>
This HTML page simply links to the three Javascript files – main.js, script1.js and script2.js.
Next, add the statement below to main.js:
var a = 10;
This statement declares a global variable a and assigns a value of 10 to it.
Next, add the following code to script1.js:
var a = "Hello"; console.log(a);
This code declares another global variable a and assigns the string "Hello" to it. In addition, it prints out the value of a.
Finally, add the statement below to script2.js:
console.log('The product is ' + a*3);
This statement prints the value of a multiplied by 3.
Now save all files and run IIFE.html. What do you think you’ll get as the output?
You’ll get
Hello
The product is NaN
Does this come as a surprise to you?
The first line (Hello) is the result of the console.log() statement in script1.js.
The next line is the result of the console.log() statement in script2.js.
As we link the three script files in the following order – main.js, followed by script1.js, followed by script2.js – the value assigned to a in script1.js overwrites the value assigned in main.js. Hence, when we try to print the product in script2.js, we are printing the product of "Hello" multiplied by 3. As "Hello" is not a number, we get NaN as the result.
This is fine if it is indeed what we intended. If that is not what we intended, we may get errors due to this overwriting. In that case, we say that the variable a in script1.js has polluted the global namespace.
To prevent that from happening, we can use an IIFE in script1.js.
To do that, we simply need to add
(function() {
})();
to script1.js and copy the original two statements in script1.js into the curly braces as shown below:
(function() { var a = "Hello"; console.log(a); })();
Now save all files and run IIFE.html again. You’ll get the following output:
Hello
The product is 30
By placing the code in script1.js in an IIFE, we have changed the variable a in script1.js into a local variable. Hence, it is no longer accessible in script2.js. When script2.js tries to access a, it’ll access the global variable declared in main.js instead. Hence, we get 30 as the product.
Clear? Good. Let’s move on.
5.5.1 Named IIFEs and IIFEs with parameters
In the previous example, the IIFE is an anonymous function and does not have any parameters. Besides anonymous IIFEs, we can also have named IIFEs. In addition, IIFEs can have parameters. An example is shown below:
(namedFunction = function (value) { var results = 5; console.log('The product is ' + results*value); })(3);
In the example above, the IIFE is called namedFunction. It has a single parameter – value. The code above executes the IIFE with 3 as the argument (i.e. value = 3). You’ll get
The product is 15
as the output.
To call the IIFE again, you can write
namedFunction(4);
You’ll get
The product is 20
as the output.