Search code examples
javascriptscopeevent-listeneriife

Using a private function inside an IIFE tied to an event listener if IIFE has not returned


I am using the modular pattern in JavaScript. I have three IIFEs in total:

  • The first one returns an object with a host of methods.
  • The second one does the same thing.
  • The third one calls the methods returned, therefore controlling the app’s logic.

All methods called inside the third IIFE are tied to an event listener for when you click anywhere in the document. If the third IIFE runs but doesn’t return, no closure is created, which means the third IIFE is popped off the stack and takes with it the variable object created during the creation phase of the execution context.

The event listener is saved in memory which calls all the returning methods from the first and second IIFE as they are global methods. However, also tied onto the event listener, is a private function that I want to run inside the third IIFE. If no closure is created in the third IIFE, how come when the click event on the document happens, the event listener recognises the private function in the third IIFE if the variable object pops off the stack with the third IIFE and is no more as no closure was created?

The controller IIFE has not returned so no closure is created and the event listener therefore calls a function that is not currently avaiable as the third IIFE has popped off the stack, does an event listener take with it a scope of when it was created? I understand how the returning methods are called as they are still global but I’m confused how the private function is called by an event listener after the third IIFE is finsihed.

See the code below. The first and second IIFEs are absent which return all the mehtods I have called in the event listener. Rather than bore you all with my long code in the project I am working on, I have simplified it below.

var scoreController = (function() {
  var score = 0;

  return {
    updateScore: function() {
      score++

      return score;
    }
  }
})();
var UIcontroller = (function() {
  return {
    updateUI: function(value) {
      document.querySelector("#displayScore").textContent = value;
    }
  }
})();
var controller = (function() {
  function setupEventListener() {
    document.addEventListener("click", updateGame);
  }

  setupEventListener();

  function privateFunction() {
    console.log("how does this work if")
  }

  function updateGame() {
    var globalScore = scoreController.updateScore();
    
    UIcontroller.updateUI(globalScore);
    privateFunction();
  }
})();

Solution

  • The controller IIFE has not returned so no closure is created

    This is a wrong conclusion. Every function can and does form a closure, if it is referenced from beyond the scope that the function is created in. It doesn't have to be returned from the IIFE for that - it could also be passed to another function, it could be stored in a global variable, or it could be attached as an event handler to the dom.

    does an event listener take with it a scope of when it was created?

    Yes. Every function does. updateGame closes over the variable privateFunction (and also over UIcontroller in a higher scope).