Reputation: 759
I keep seeing warnings not to use global variables in JavaScript, but it seems that the only reason people say that is because the clogs up the global namespace. I can imagine this being easily fixed by putting all of the variables into one big object. Now the question is: are there any other reasons not to use global variables other than convenience sake? Are there any performance or compatibility issues involved with them?
Upvotes: 47
Views: 50423
Reputation:
To add another global hazard in JavaScript with globals, they can end up hiding standard APIs.
var focus = false;
const elem = document.querySelector('#name');
elem.addEventListener('focus', _ => { focus = true; show(); });
elem.addEventListener('blur', _ => { focus = false; show(); });
function show() { console.log('focus:', focus); }
<input id="name" type="text">
In the code above I made a global variable called focus
but it's overriding the focus
function on window
. I might later include a library that calls window.focus
and it will fail.
New functions and properties are added to window
from time to time so there's a chance you'll name something that clashes with the browser later.
Similarly, I've seen (and written 😅) code like this
if (!window.MyAPI) {
window.MyAPI = ...
}
...
MyAPI.doTheThing();
or the shortened version
window.MyAPI = window.MyAPI || ...
...
MyAPI.doTheThing();
The problem with this particular pattern is the browsers might release a new API called MyAPI
in which case the check will not replace the global and doTheThing
won't exist.
This exact issue happened with Reporting API. A very popular library had a class or function named Report
which it tried to install globally and conditionally like above. Upon browsers trying to ship the Reporting API
, every site using that library broke.
There are 2 solutions.
(poor), don't conditionally assign the global
window.MyAPI = window.MyAPI || ... // bad!
window.MyAPI = ... // still bad but better
In this case you'll at least override the new browser API with your own. Of course now you have the issue that some other library may want to use the new API end you've effectively hidden it.
(good), Don't use globals.
The pattern above is arguably left over from pre es6 module days. Now-a-days it's arguably better to put your library in a module.
You can then import it into a local or at least module level variable
import MyAPI from './MyAPI.js';
MyAPI.doTheThing()
Note: MyAPI
in this last sample is and is not a global variable. It's only accessable by the current module so it is global to the module but not to other modules.
Note 2: One exception to the advice above is for polyfills of standard libraries.
Note 3: If it's not clear, globals in JavaScript get assigned as properties of the global object which in the browser is window
. Further, a property added to the global object becomes a global.
Example:
console.log('foo' in window); // prints false
console.log('foo' in window); // prints true
var foo = 123;
window.bar = 456;
console.log(bar); // prints 456
Upvotes: 1
Reputation: 2571
In general, we should group similar code and variables together and erect fences around them. This is called a class, and it really helps to organize a program. Good organization makes it easier for others to read your code, easier to maintain the code as the program grows, easier to write unit tests, and easier to reuse the code and avoid code duplication.
All of this is essential when making the jump from a small program with one maintainer, to a medium or large program with multiple people working on it.
Globals have no fence around them and are not grouped with any other code. They can potentially affect any other part of the program, and it's hard to see at first glance what parts they affect. Globals need to be mocked in unit tests, and it is not clear at first glance that they need to be mocked just by looking at method definitions.
Upvotes: 0
Reputation: 1279
The global variable which you have created might overwrite the existing window object properties. Because the global variables are accessing in global context i.e. window object.
Upvotes: 0
Reputation: 35276
In a nutshell, Global variables cause (and more) the following issues.
1) Variable naming collisions - If you're working on a team and both yourself and your co-worker use the same variable name on the global scope, the variable defined last will overwrite the initial variable. This obvious can have devastating consequences.
2) Security - Specifically on the web, every user has access to the Window (or global) object. By putting variables on the global scope, you give any user the ability to see or change your variables.
3) Slower - This is arguably negligible, but it still exists. The way JavaScript variable lookups work is the JavaScript engine will do a lookup on the current scope the variable is being looked up in. If it can't find it, it will do a look up on the next parent scope. If it doesn't find it there, it will continue looking upward until it reaches the global object looking for that variable. If all of your variables are located on the global scope, the JavaScript engine will always have to go through every scope in order to finally reach the global scope to find the variable.
Upvotes: 8
Reputation: 1459
Global variables can significantly increase coupling, significantly reduces the scalability and testability of your code. Once you start using globals, you now have to know where and how the variable is modified (i.e. breaking encapsulation). Most of the literature and conventions out there will argue that performance is the least of your concerns when using globals.
This is a fantastic article outlining why global variables cause headaches.
Upvotes: 17
Reputation: 5994
There shouldn't be any problem using global variables in your code as long as you are wrapping them inside a uniqe namespase/object (to avoid collision with scripts that are not yours)
There is one adventage of using global variable in javascript, and it derives from the fact that javascript is not a strong type language. there for, if you pass somes complex objects as arguments to a function, you will probebly lose all the intellisence for those objects (inside the function scope.) while using global objects insteads, will preserve that intellisence. and when you have intelisence, it actually can improve the debugging time (as opposed to what others said...)
I personally find that very usful and it certainly have place in my code.
(of course, one should alwayse make the right balance between locals and globals variables)
Upvotes: 3
Reputation: 2225
If your script is very long and you use these variables from lots of functions it will increase your debugging time since the value of the global variable could have been changed from anywhere so if you are tracking where this changed to a non-expected value you'll have to check them all.
This scenario is even more painful if different programmers modify this variable from other scripts included in your page.
Upvotes: 5
Reputation: 11342
Basically, because they can be accessed from any script on the page and because you can repeat it's name in the same scope. That's why a lot of Javascript engines use this code:
(function(){
var foo = 'foo',//Local
bar = 'bar';//Local
window.globalVar = foo + bar;//Global
})();
alert(foo);//Error
alert(bar);//Error
alert(globalVar );//'foobar'
Upvotes: 1
Reputation: 53291
They clutter up the global namespace and are slower to look up than local variables.
First of all, having many global variables is always a bad thing because it's easy to forget you declared a variable somewhere and accidentally re-declare it somewhere else. If your first variable was local then you don't have a problem. If it was global, then it just got overwritten. This gets even worse when you get into implied globals (e.g. when you say someVar = someValue
without declaring someVar with the var
keyword).
Secondly, global variables take longer for Javascript to "find" than local variables. The difference in speed isn't huge, but it does exist.
For further reading and a more in-depth explanation of why globals are considered bad practice, you may want to check out this page.
Upvotes: 49