Global Variables and Best Practices

I’ve been reading on best pratices in javascript, and aparently using global variables is bad :dizzy_face:

I have a general idea as to why it is not recomended, but I don’t understad it completely. Since I learned programming with Java i’m used to doing stuff like this:

 private int thisThing;

 public int getThisThig(){
     return thisThing;
 }

 public void doSomenthing(){
  //do something with thisThing;
 }

So could you explain me why it is a problem to use global variables and how to avoid using them, especially when I need to expose a variable to different scopes. Thanks for the help guys.

There are two big problems with globals. First is collisions. If everyone used global variables, the more code you write, or as you pull in more libraries and frameworks, the chances of you using a variable with the same name as something/someone else increases. Once a name collision occurs, bad things start to happen as the value of that, now shared, variable becomes unpredictable.

Now, its been a while since I’ve written much Java, but I don’t remember there being any global variables there. Everything was in classes, and if you wanted shared data, you’d have a static class with some variables in it rather than just having a global variable. And then, you have additional collision protection from use of packages and imports. Is your snippet a complete file? Or is that something that would be in a class block? In a class block, thisThing would be encapsulated within the class instance keeping it out of anyone else’s hair.

JavaScript, conversely, doesn’t package everything up into nice little class bundles like Java does. Basically everything starts in global (particularly when the browser’s concerned) and its up to you to keep things as tight as possible. You’ll see people use certain patterns to create namespaces like:

var com = com || {};
com.domain = com.domain || {}; // etc

Though IIFE’s are more common now:

(function(exports) {
  var value = 1; // local to this function, not global, but can be used anywhere in this block
  function MyClass() { }
  // ...

  exports.MyClass = MyClass;
})(window); // window is the global object in browsers

// you may also see the IIFE return a value with an assignment at the start if creating a single export

Outside of the browser, in Node, for example, there are modules which are more self-contained, each with their own scope. Variables there are not inherently global. To make things global, you have to attach them to the global object.

// MyClass.js module for Node.js
var value = 1; // local to this module
// global.value = 1; // would be global equivalent
function MyClass() { }
// ...

module.exports = MyClass;
// exports.MyClass = MyClass; // alternative, named export

Then in a file where you’d want to use the class you’d explicitly require it, not unlike including <script> tags in HTML, only in Node, you control how it gets defined, further helping prevent naming collisions.

var MyClassImported = require('./MyClass.js');
// ...

Node.js handles modules automatically. But you can also use them on the web using a preprocessor like Webpack which effectively compiles modules by reading the require dependency tree and creating a single file with a bunch of wrappers that maintains module encapsulation.

Then there’s also AMD which allows you to load scripts asynchronously… ok, well I guess what I’m getting at is that JS is pretty open, and when it comes to maintaining order, there are a number of different, often confusing options.

But to get back on point, #2 is reducing side effects. Having global variables breaks encapsulation spreading out dependencies and making them more open to change. Anyone can change or delete a global variables making your program more prone to errors. The more you pull things in, keeping them out of the reach of others, the safer you’ll be. It also makes it more easy to test and refactor your code. After all, the less you have to worry about (things defined over here, things changing over there), the easier your code is to work with. And not even just you, but any other poor sap that has to maintain your code after you’re gone.

Functional programming has gotten more popular with JavaScript lately, and with that the promotion of pure functions. Pure functions do not change anything outside of themselves. This makes it clear that, when called, nothing changes - no unwanted or unexpected side effects. You put something in and you get something out. Nothing else.

// pure function
function addOne (x) {
  return x + 1;
}

// impure function
var x = 0;
function addOne() {
  x += 1;
}

The less state you have to consider, the easier it is to handle. These functions are also more reusable and transferable because of their lack of external dependencies.

Using globals is the worst case scenario for something like this because anyone can access a global variable, and from anywhere. When you use a global variable, you might not even be in code that even initially defined the global variable. So where is it set up? What is its initial value? Who can change it? What can it even be? The less you have to ask questions like this, the easier it will be for you to write code.

3 Likes