Search code examples
javascriptrevealing-module-pattern

javascript revealing module pattern with multiple files/modules and global vars


I apologize if this has been asked elsewhere, but all the info I've seen doesn't really help me understand both the answer and best practice.

I'm attempting to use the revealing module pattern for javascript. I have a base js file that contains methods and properties that are needed on every page of the application.

Then each page has its own js file that has it's own unique functions and variables, but also needs to reference the variables in the base js file.

I seem to be really misunderstanding variable scope, or how I'm setting this up is somehow very bad, because I'm getting confusing results.

Questions:

  1. If i'm structuring this wrong, what is the right way?
  2. How can I access variables correctly across modules?
  3. Am I correct to initialize the modules on doc ready?

What I'm doing right now is this:

var base = (function() {
    init = function() {
        url = $(location).attr('href');
        url = url.substr(-1) === '/' ? url.slice(0, -1) : url;

       segments = url.split('/');

        baseUrl = this.segments[0] + '//' + this.segments[2] + '/';

        resource = this.segments[3];

        this.segments = segments; //need access to this across all pages
        this.resource = resource;  //need access to this across all pages
        this.baseUrl = baseUrl;  //need access to this across all pages
    }
}

    doStuffGlobally = function() {
        //do stuff for all pages
    }

   return {
        init: init,
        baseUrl: this.baseUrl,
        segments: this.segments,
        resource: this.resource
  };
}());
$(document).ready(function() {
    base.init();
}

And on another Page I'm doing this:

var otherPage = (function() {
    init = function() {
      //do otherPage stuff;
    }
}
doStuff = function() {
    base.doStuffGlobally(); //need to access this.
    console.log(base.segments); //need to access this.
}

   return {
        init: init
  };
}());
$(document).ready(function() {
    otherPage.init();
}

Solution

  • You don't need an init method for your base module, it doesn't need to wait for domready but can (and should) run immediately. So write

    var base = (function() {
        var url = $(location).attr('href');
        if (url.substr(-1) === '/') url = url.slice(0, -1);
    
        var segments = url.split('/');
        var baseUrl = this.segments[0] + '//' + this.segments[2] + '/';
    
        var resource = this.segments[3];
    
        function doStuffGlobally() {
            //do stuff for all pages
        }
    
        return {
            baseUrl,
            segments,
            resource,
            doStuffGlobal,
        };
    }());