1

I'm using a framework (meteor, but doesn't matter for the question I guess) which provides separate functions..

My problem is I realize I am using more and more global variables in order to make them accessible between these functions. For example the map object:

Meteor.startup(function () {
  map = L.map('map_canvas').locate({setView: true, maxZoom: 21});
  L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
      attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
  }).addTo(map);
});

I need to access map everywhere to manipulate my maps(with the use of Leaflet) For example:

Template.messages.events({
  'click .delete-message': function (e,t) {
    e.stopPropagation();
    removeItem(e.target.id);
  },
  'click .message': function (e,t) {
    console.log('event clicked');
    map.setView([e.target.getAttribute('data-lat'),e.target.getAttribute('data-lng')], 16);
  }
});

I have the same problem when I want to create a marker object that I want to use in different places...

Is it that Meteor is built this way, or are there more proper/clean JS alternatives rather than making stuff global?

edit Thanks for your answers, could you please add an example of code using for example one of the patterns you mention but based on my code? This way I could understand it much better.

George Katsanos
  • 13,524
  • 16
  • 62
  • 98
  • 1
    You may want to check out this other, possibly similar [question/answer thread](http://stackoverflow.com/questions/5063878/javascript-global-variables-best-practices?rq=1). – summea Mar 18 '13 at 21:56
  • 1
    In addition to the "namespace" option, you can also use a single closure for all your code (aka module pattern) so that variables are available to your functions but no one else. – RobG Mar 18 '13 at 22:29
  • 1
    [This article](http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth) is great. – jahroy Mar 19 '13 at 02:51
  • @jahroy Indeed, it is. – George Katsanos Mar 19 '13 at 17:28
  • 1
    @ everyone I updated my question.. It would help a lot in order to put theory into practice, to have an example based on my code? – George Katsanos Mar 19 '13 at 17:32

1 Answers1

1

There are many ways to make js variables and functions not global.

  1. You can use an object as a hash map and access your variables with dot notation. The object is still global but at least you fewer global names that could conflict.
  2. You can use namespace.js.
  3. You could use pseudo-oo style using closures.
  4. You could use coffeescript.
  5. Aside from namespace.js, a lot of frameworks like dojo.js allow for modules.
  6. Probably many other options.

Dojo.js and I think require.js encourage modular design. (among others) Namespace is pretty easy to include and use and may solve your problem with the smallest amount of code change. I've used it in the past to go from global to more OO style.

Option 1, Hashmap

var GKApp = new Object();
GKApp.map = blah;
GKApp.size = 1;
GKApp.doSomethingWithMap = function() {
    GKApp.map.blah();
}
// Now the only global is GKApp.
// Later, make the call. 
GKApp.doSomethingWithMap.call();

Option 3, Closures

You can use a pure javascript closure as shown below or wrap this in a define using dojo.js or require.js.

GKApp = function(pmap) {
    // dbg.log("GKApp constructor.");
    // You can consider the closure to 'begin' here.

    // ********************************************************
    // @private variables:
    // ********************************************************
    var map = pmap;

    /**
     * @privileged method which has access to variables in the closure.
     * These variables are not available outside of the closure.
     * An anonymous function has access to variables in the outer scope or, the closure.
     */
    this.doSomethingWithMap = function() {
        map.blah();
    };
};

// Later, instantiate an object and use it. 
var gkApp = new GKApp(map);
gkApp.doSomethingWithMap();
Jess
  • 23,901
  • 21
  • 124
  • 145
  • It's a bit more than that. A hash for example means something else in the context of languages that don't use the word "hash" to mean an associative array. It means a calculated value that can be used as an identifier to a piece of data. MD5 and CRC32 for example are examples of hashes. On the other hand, actually calling an object what it is also serves to educate novice programmers on the dynamic nature of objects in js. – slebetman Mar 19 '13 at 05:46
  • 1
    Jessemon thanks for this detailed answer. I had read about the modular design and Closures before, but now that I actually try to implement that I have the more practical questions: The first that comes to mind is, a closure is supposed to limit the scope of a variable. So far so Good. But what I am asking is how can I safely share a variable between different functions without polluting the global scope. I guess using the modular pattern helps - the whole gist is using "return" - or am I getting wrong ? – George Katsanos Mar 19 '13 at 17:31
  • I have the map object - which is basically my main problem as I want to access it in different functions.. – George Katsanos Mar 19 '13 at 18:47