javascriptmodulemodular-design

Module design pattern encapsulation


Given this code in module design pattern:

    var HTMLChanger = (function() {
      var contents = 'contents'
    
      var changeHTML = function() {
        var element = document.getElementById('attribute-to-change');
        element.innerHTML = contents;
      }
    
      return {
        callChangeHTML: function() {
          changeHTML();
          console.log(contents);
        }
      };
    
    })();
    
    HTMLChanger.callChangeHTML();       // Outputs: 'contents'
    console.log(HTMLChanger.contents);  // undefined
<div id="attribute-to-change"></div>

We have this line:

console.log(HTMLChanger.contents);  // undefined

Now what if we had a code that would give us another result:

console.log(HTMLChanger.contents);  // 'contents'

What is the benefit of previous line and module design pattern code assotiated with it?


Solution

  • console.log(HTMLChanger.contents); // undefined

    Your HTMLChanger variable is assigned to the return value of an IIFE (immediately invoked function expression). The return value is here:

      return {
        callChangeHTML: function() {
          changeHTML();
          console.log(contents);
        }
      };
    

    So it is set to an object containing one property named callChangeHTML. The variables contents and changeHTML are only defined in the scope of the IIFE, and are not properties on the returned object (otherwise, it would defeat the purpose of this pattern, which is to hide implementation details). Code outside of the IIFE has absolutely no way to access them, unless you add more functions like getters and setters to the returned object. That would look something like this:

        var HTMLChanger = (function() {
          var contents = 'contents' //this is just a variable! not a property!
        
          var changeHTML = function() {
            var element = document.getElementById('attribute-to-change');
            element.innerHTML = contents;
          }
        
          return {
            callChangeHTML: function() {
              changeHTML();
              console.log(contents);
            },
            getContents: function() {
              return contents;
            }
          };
        
        })();
        
        HTMLChanger.callChangeHTML();       // Outputs: 'contents'
        console.log(HTMLChanger.getContents());  // Also outputs 'contents'
    <div id="attribute-to-change"></div>

    What is the benefit of previous line and module design pattern code assotiated with it?

    You hide the implementation away where no code outside the function can access it, and you expose only an interface which contains functions to interact with the implementation. In other words, it's a way of creating a "black box" that only has a select set of functions on it instead of lots of functions and variables that you will likely never end up using in a context external to the implementation, such as other code outside of the module.