1

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();
}
hyphen
  • 2,368
  • 5
  • 28
  • 59
  • You didn't put `doStuffGlobally` in the `base` object? – Bergi Feb 24 '19 at 13:51
  • `base.segments` should in fact work, assuming that `base.init()` has already been called. – Bergi Feb 24 '19 at 13:52
  • 1
    JS doesn't have implicit variable scope. All your variables, even those within the module pattern IIFE and the `init` function, are global - you must declare them with `var`! – Bergi Feb 24 '19 at 13:52
  • `baseUrl: this.baseUrl,` in that object literal doesn't work. What do you expect `this` to refer to here? And what value do you want to initialise the property with? – Bergi Feb 24 '19 at 13:55
  • I essentially just want to keep things DRY. So for every page the user navigates to, i want to get and parse the url out into an array of segments. I want those variables to be accessible in other modules so i'm not repeating myself. – hyphen Feb 24 '19 at 13:57
  • Sure, but why do you parse the URL in that `init` function (which isn't called until dom ready)? Would be much easier if you just did it immediately when creating the module. – Bergi Feb 24 '19 at 13:58
  • yes, I suppose you're right. I believe my thought process was that the init function was like a constructor and i was setting up all my object vars in that function. Like I said, I'm probably not doing it right.. – hyphen Feb 24 '19 at 14:00
  • So, i should maybe set up those vars in a script tag in the header or something? I'm not sure of the best way to structure this.. – hyphen Feb 24 '19 at 15:56

1 Answers1

1

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,
    };
}());
Bergi
  • 630,263
  • 148
  • 957
  • 1,375