Lesson Tuesday

This lesson is optional further exploration. You can skip it entirely if you want. We'll use a more advanced technique to refactor our code a bit more. Specifically, we'll use an IIFE (Immediately-Invoked Function Expression) to further clean up the code we wrote in the last lesson. IIFEs have their use cases but they really aren't necessary for beginners or even intermediate developers to know about.

Why even bring up IIFEs if they aren't an essential concept right now? Well, the following code in our async...await example is a bit annoying:

src/main.js
async function makeApiCall(city) {
  const response = await WeatherService.getWeather(city);
  getElements(response);
}

We create a named async function simply because we can't use the await keyword outside an async function. It kind of feels silly. With an IIFE, we can get rid of the named function and do the following instead:

src/main.js
$(document).ready(function() {
  $('#weatherLocation').click(function() {
    let city = $('#location').val();
    clearFields();
    (async function() {
      const response = await WeatherService.getWeather(city);
      getElements(response);
    })();  
  });
});

No named function needed! Instead, we do the following:

(async function() {
  const response = await WeatherService.getWeather(city);
  getElements(response);
})();

So what exactly is going on here? And what's with the weird additional parens? Well, that's the syntax for an IIFE - a function that's immediately invoked. Here's the syntax in a nutshell:

// Pseudocode example!

(function() {
  // A function to be invoked immediately.
})();

The key thing here is that we wrap the function itself in parentheses and then we also have a closing parens at the end of the IIFE. The parentheses around the function are so the JavaScript compiler doesn't throw an error. The parens at the end invoke the function just like we'd invoke any named function. We can even use a named function for an IIFE:

// Pseudocode!

(function thisIsImmediatelyInvoked() {
  // A function to be invoked immediately.
})();

So why use an IIFE? Well, we've seen one potential use case - to use an immediately invoked unnamed async function so we can use the await keyword.

The biggest benefit of IIFEs, though, is data privacy. Any variables or data in an IIFE are scoped to it - and aren't available elsewhere. If we didn't use an IIFE, those variables will be available in other scopes - perhaps even the global scope, which isn't good.

Let's quickly demonstrate:

(function() {
  const secret = "This is a secret!"
})();

secret

If we run this in the console, we'll get a secret is not defined error. As we know, it's very important to scope our code. For instance, think about the projects we did before we implemented JavaScript. We might have something like this:

function doSomething() {
  // This function will do something.
}

$(document).ready(function() {
  doSomething();
});

Well, that doSomething() function is available globally - we could even access it by typing in window.doSomething() in the console when we run our project.

So traditionally, it was common to use an IIFE to wrap the code in the user interface source code like this:

(function() {

  function doSomething() {
    // This function will do something.
  }

  $(document).ready(function() {
    doSomething();
  });
})();

This way, the doSomething() function will no longer be in the global scope (or accessible via the window object). It would just be available within the scope of the IIFE, which is where we want it.

Fortunately, webpack solves this problem for us, too, and doesn't allow code to leak into the global scope, so you won't see an IIFE used in this way with webpack. They can still be a useful tool for scoping code, though, and they can make an async function look a little bit cleaner.

The example repository hasn't been updated to include this code because it's optional. However, if you are interested in working with IIFEs, we recommend trying them out when you are writing async functions.

Lesson 24 of 29
Last updated more than 3 months ago.