Need help / help getting rid of globals

Yes, this is another topic about global variables. I've searched for them a bit. But most of the topics are just WHY not to use globals, and I'm convinced I shouldn't, and I'm more interested in HOW not to use them, and I'm still not sure.

I am working on a project and it works wonders, but at the moment I am using about 50 global variables and this number continues to grow. Right now I have laid out things in multiple .js files. Like load_chunks.js, load_images.js, render_map.js, player_actions.js, input.js, distribute functions depending on what they are for. And I have included all global variables in settings.js.

I currently use these globals for these reasons:
1. Calculation based on some other globals that don't change much or after loading. By doing this once and storing it in a global variable, I no longer need to repeat the calculations again. If I didn't store it in a (global) variable, Javascript would have to do the computation many times per second, in some cases even up to several thousand times per second.
2. When a global variable is required in many functions. Like this World variable that I use to store data for the appearance of the world. This variable is a multidimensional array. For example, World [y] [x]. Load_chunks.js adds additional data to this variable or removes data if you move too far. This variable is also needed in render_map.js to create the map, and also needed in player_action.js to see if you can step on that particular location.
3. Settings; This way, the number in the variable remains the same unless I change them in my script. Instead of going through my scripts and changing numbers manually after a long search and thinking what that number is, I put that number in 1 variable and called that variable many times in my scripts. These variables are in some cases also needed in other places.

Also I would like to mention that I am not using classes, and perhaps for this reason I have never traversed globals ...?

So how do I get rid of my globals, or should I not? Hopefully you can show me or write an example script for me (or a link to it) of how I should go about doing this. This is the fastest way to find out.

+3


source to share


3 answers


Insert variables inside function closure

One common way to eliminate the global is to have it inside a function closure:

(function() {
     var declareYourFormerGlobalHere = 0;

     // put all code that uses the variable inside this closure
     // the variable persists for this code to use, but is not actually global
})();

      

Here are some examples of use:

// example keeping track of a running count and a cached DOM element
(function() {
    var cntr = 0, obj = document.getElementById("test");
    setInterval(function() {
        ++cntr;
        if (obj.value < cntr) {
            // do something
        } else {
            // do something else
        }
    }, 1000);
})();

// example keeping track of a time of last click
(function() {
    var timeOfLastClick = 0;
    document.getElementById("run").addEventListener("click", function(e) {
        var now = new Date().getTime();
        // only process click if more than 2 seconds have passed since last click
        if (now - timeOfLastClick > 2000) {
            // OK to process the click
        }
        timeOfLastClick = now;
    });
})();

      

Sometimes you can actually wrap all of your code, or almost all of your code, in a single closure, like this, and all of your current globals become local variables within the closure, rather than actual globals. jQuery uses this technique to declare a lot of constant variables that it uses, none of which are globally valid.


Use a single namespace object

Another common technique for reducing the number of globals is to use the concept of a namespace. In this concept, you declare one global object and put other constant variables as properties of that single global object. This still leaves you with one global variable, you can have as many properties as you want from that single global.

var myNamepaceObject = {};
myNamespaceObject.var1 = "foo";    
myNamespaceObject.var2 = "whatever";

      



This method is also used by jQuery since all globally available functions offered by jQuery are accessible from a jQuery object such as jQuery.extend()

or jQuery.contains()

. jQuery provides a single global variable, and many other globally accessible functions are then available as properties of that single global object.


Module template

What is commonly referred to as a "module pattern" uses a combination of the above two methods, where you have a single module variable that uses properties and closure variables.

var MODULE = (function () {
    var my = {},
        privateVariable = 1;

    function privateMethod() {
        // ...
    }

    my.moduleProperty = 1;
    my.moduleMethod = function () {
        // ...
    };

    return my;
}());

      

You can see a discussion of this design pattern in these links:

JavaScript Module Pattern: Depth

Learning Javascript - Module Pattern

Mastering the module template

JavaScript module template with example

+2


source


I am convinced that I should not, and I am more interested in HOW not to use them, and that I am still not sure.

load_chunks.js, load_images.js, render_map.js, player_actions.js, input.js,

strongly hints at a procedural implementation, meaning your architecture probably has multiple functional elements, and you are passing data between those functions. That's where your globals come from.

So how do I get rid of my global variables (...)

To change this, you need to structure your system in an object or component based approach, that is:

  • encapsulate data + relevant functions with objects in your problem area eg. have an object World

    that contains objects Avatar

    , Buildings

    , Airborne

    etc. (or whatever your project is).

  • separate the problem logic logic from the presentation logic (for example, use an MVC architecture )

  • then your project organizes the interaction between the view and model objects, essentially exchanging messages between them.

To facilitate this, I suggest these thin frames or some equivalents as appropriate for your runtime:



  • requirejs - encapsulate modules into globally managed components
  • backbonejs - have an efficient, tested model / view, class / object model (actually built for use with a REST-style backend, but that's not a strict requirement).

Code structure

Typically, I build my applications in such a way that there is one .js file for each component / module of the object. A module in this sense contains both a class definition and a corresponding set. Modules are driven by requirejs and class definitions are done using backbonejs.

I hope you can show me or write an example script for me

/* define a class e.g. in someclass.js */
define(['backbone'], function($B) {
    var SomeClass = $B.Model.extend({
       // all instance variables, methods etc. follow
       someVar : value,
       someMethod : function() { ... }, 
    });
    return SomeClass;
});

/* use the class, e.g. in app.js */
require(['someclass'], function(SomeClass) {
   var instance = new SomeClass({ initial model attributes });
   var value = instance.get('attribute');
   instance.someMethod();
   ...
});

      

+3


source


I had the same problem before, but it was a big problem as we had 3rd party javascript code and our code worked on clients' websites, so we have to find a way to omit the appearance of the global variable to be short: Use 1 global variable namespace and do all the rest for it:

GlobalVariable = {}
GlobalVariable.var1 = "var1"
GlobalVariable.var2 = "var2"

      

You can also make it more useful and divide it into groups:

 GlobalVariable.helper = {}
 GlobalVariable.helper.var1 = "var1"
 GlobalVariable.helper.var2 = "var2"

      

so that you can use the same names under different groups.

and if you want to omit it entirely, you can use:

(function(document, window) {
    // all variables here is global only inside the scope
}(document, window));

      

+1


source







All Articles