Is there any difference between this two JavaScript patterns? - javascript

Looking at some JavaScript libraries and other people's code I've seen two common patterns, I don't know if there is a difference or advantage in using one of them. The patterns look sort of like this:
1.
var app = (function () {
// Private vars
// Module
var obj = {
prop: "",
method: function () {}
};
return obj;
})();
2.
(function () {
// Private vars
// Module
var obj = {
prop: "",
method: function () {}
};
window.app = obj;
})();
Are this patterns the same or do one of them has an advantage or different use than the other?
Thanks in advance.

The second assumes the existence of an object called window in the parent scope and assigns a property there.
The first one leaves it up to the caller to make the assignment, and does not depend on a window being defined (which it probably is only inside of a web browser).
So, I'd say the first one is definitely better (more self-contained, less environment-dependent).

tl;dr: pick one method and be consistent.
In my opinion, the first method has a slight advantage for readability. In my head, when I read it, I see that, "module app is being defined," and that everything inside of this closure belongs to that module. This is a natural decomposition for me and imposes the object oriented nature of the module about to be defined.
Another reason I favor the first method is that it is cleaner to change the scope into which a module is defined. Every module you define wont need to be part of the global scope. Using the second method, if the scope isn't injected by passing in a parent object as Jared Farrish illustrates with his jQuery example, then you run the risk of breaking your code if you decide to change the name of that parent object. This example illustrates the point:
var namespace = {
subns: { ... }
};
(function() {
var module = { ... };
namespace.subns.someModule = module;
}());
Anytime the identifiers namespace or subns change, you also have to update this module and any other module that follows this pattern and adds itself to the same object.
All in all, neither method one nor method two (with dependency inject) is "better" than the other, it is simply a matter of preference. The only benefit that can come from this discussion is that you should pick one method and be consistent.

They are both accomplishing the same thing, to create an object in the global namespace at the time the code is run.
One isn't more "hardcoded" than the other, since neither is doing any kind of function prototyping in which you could create clones of the object with the new keyword. It's just a matter of preference, in my opinion.
For instance, jquery does something akin to the latter:
(function( window, undefined ) {
// Use the correct document accordingly with window argument (sandbox)
var document = window.document;
var jQuery = (function() {
// Define a local copy of jQuery
var jQuery = function( selector, context ) {
// The jQuery object is actually just the init constructor 'enhanced'
return new jQuery.fn.init( selector, context, rootjQuery );
},
// Map over jQuery in case of overwrite
_jQuery = window.jQuery,
// Map over the $ in case of overwrite
_$ = window.$,
...
But Prototype JS Library does the former:
var Prototype = {
Version: '1.6.1',
Browser: (function(){
var ua = navigator.userAgent;
var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]';
return {
IE: !!window.attachEvent && !isOpera,
Opera: isOpera,
WebKit: ua.indexOf('AppleWebKit/') > -1,
Gecko: ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1,
MobileSafari: /Apple.*Mobile.*Safari/.test(ua)
}
})(),
...
I don't know of any reason why one is better than the other, or that they accomplish their task differently (to create the app object in the window namespace).

In the first example, if app defined within another function, app will only be available in that local scope, whereas in the second example the app variable is explicitly assigned to the global scope.
In the second example, the app will only be assigned to the global scope if defined in the global scope outside of functions.

The second form has a slight advantage in that you have a completely self contained function; for example you could then have a standard header and footer for your JS files.
The part I'm not completely sold on is the local variable inside the block. I tend to prefer this:
(function () {
// Private vars
// Module
window.app = {
prop: "",
method: function () {}
};
})();
although that breaks down a bit when you're doing more than one thing, such as building up an object with multiple methods rather than a single object as in this example.

Related

Passing a window object into Javascript namespace

I'm trying to better understand namespacing in javascript and found an example of a javascript Immediately-invoked Function Expression that is taking the window object as a parameter. Here is the code from it:
var CG = CG || {};
CG.main = (function(window) {
var FOCAL_LENGTH = 8.0;
var context, width, height, startTime;
var init = function() {
var element = document.getElementById("canvas1");
context = element.getContext("2d");
width = element.width;
height = element.height;
startTime = (new Date()).getTime() / 1000.0;
tick();
}
var original_onload = window.onload || function() {};
window.onload = function() {
original_onload();
CG.main.init();
}
return {
init: init,
draw: draw_shape,
clear: clear_canvas
};
}(window));
At the end of the namespace definition, there is a line with window in parenthesis which I am confused as to the functionality of. I think that the purpose of adding the parameter of window to the end of the definition is to bind the global window variable to the namespace which will then add different properties to the window, but I can't really be sure.
In another example there is a random variable name passed into the definition of a namespace, and at the end of the namespace definition, the actual name of the namespace is passed as a parameter:
var namespace = namespace || {};
// here a namespace object is passed as a function
// parameter, where we assign public methods and
// properties to it
(function( o ){
o.foo = "foo";
o.bar = function(){
return "bar";
};
})(namespace);
console.log(namespace);
So there are really a couple of questions here:
What is the functionality of passing a parameter at the end of the namespace definition?
If my intuition for how this all works is incorrect, what is the general structure for this kind of namespace creation javascript?
Clearly I'm very new to this so any help would be appreciated, thanks.
I will try to explain this as well as I can but my understanding of it comes from Kyle Simpson. He's awesome, you should look him up. :-D
You are asking a question about immediately invoked function expressions (IIFE), passing arguments to them, and why someone would do that.
First, the reason IIFEs are being used in this context is to restrict the scope of variables.
This is important because as programs become larger and many pieces are added on you can easily have conflicts from one variable to another.
app.js could have
variable = "thing";
and shortly after somethingelse.js could have
variable = "not thing";
That is a huge problem. It is avoided in javascript by creating "modules" or functions that immediately run and run once.
That way, the variables and methods you create in your function don't "pollute the global scope/namespace."
BUT, what if you NEEDED or WANTED something to be available on the global window object?
Well, you could do that by adding it to the "window" which is the global scope in javascript.
(function Module(window){
var _thing = "private thing that only exists in this function";
window.thing = _thing;
//IS NOW AVAILABLE GLOBALLY AND EXPLICITLY ON WINDOW OBJECT
//window.onload you can wait for DOM/page before running the rest
})(window);
You also could have named it anything you wanted inside your function:
(function niftyModule(global){
global.variable = "nifty text!";
})(window)
This becomes especially important when you are using multiple libraries.
For some reason, everyone likes to use "$" as the representation of their library so you can access their private methods (which are really just functions inside an IIFE too! (its a really popular way to build good stuff).
So, what if you are using jQuery and 2 other libraries that also use $ to access their public methods/api??
Easy, you can assign which one you want to assign what variable inside your function/module scope by passing it in as an argument!
(function NiftyModule(window, $){
//Now, every time you use $ in here it means jQuery and not something else!
})(window, jQuery);
It is important to play around with functions and scope. Build some variables in different ways.
For example, is....
var text = "nifty text";
the same as
text = "nifty text";
How about if you do the same thing inside functions? How do those two versions differ?
Also, get used to building your own programs in IIFEs and properly restricting the scope of the code you are writing.
You can also return objects from functions which have the methods and variables you want to access globally on them without adding them to the window object.
It is complicated at first but in the future it saves you a lot of trouble and bugs!
Finally, In your example of:
//initialize a global variable called namespace. If this already
//existed then assign it the previous values. If not, make it an empty
//object.
var namespace = namespace || {};
//pass namespace into an IIFE. Within the IIFE refer to namespace as "o"
(function( o ){
//assign a variable to namespace
o.foo = "foo";
//assign a method to namespace
o.bar = function(){
return "bar";
};
})(namespace);
//now when you log namespace it will have those properties.
console.log(namespace);

Hardcore javascript module scope

The problem : I want to iterate over my list of functions, and modify them in place, using code like:
for(var funcProperty in scope) {
scope['_'+funcProperty] = scope[funcProperty];
scope[funcProperty] = wrapFunctionInTryCatchBlock(scope['_'+funcProperty]);
}
I want to do this without explicitly having to go through all my functions, and add them to some object, thereby creating the required scope. I don't want to do that because then all the functions, which call each other, will have to have their names modified and lengthened to become:
funcName becomes scopeObject.funcName : annoying.
I could do this quite easily if my functions were in the global object, i.e, Window, however I don't want to pollute the global namespace, so I have put them in a module, like so:
var MyModule = (function() {
function privateFunc1(...) {...}
function privateFunc2(...) {...}
var public_api = {
coolName : privateFunc1
};
return public_api;
}());
However, I can see and find no way to access the scope object that exists in the immediately executed function call the return value of which is assigned to MyModule.
I tried doing this, from within MyModule:
console.log(this)
To see if we did have access to the scope, somehow, yet, of course, it turned out that this referred to Window.
My question is really: What is the scope object that the methods in MyModule private scope are assigned to, since it is not the global object, and it does exist, since all the functions have implicit access to it. Is there any way I as a JavaScript programmer can explicitly access the scope object and enumerate its properties or is that FORBIDDEN?
I'm not going to rush to accept this as the answer, but I have found one possible solution that I am happy with.
Definition of "happy with" in this case is : minimal extra work, almost no changes to existing code.
The solution
We modify the module code like so:
// $ = wrapFunctionInTryCatchBlock
function $(fun) {
return function() {
try {
return fun.apply(this,arguments);
} catch(err) {
console.log("Error",err,err.stack);
}
};
}
var MyModule = (function() {
var privateFun1 = $(privateFun1(...){...});
var privateFun2 = $(privateFun2(...){...});
var public_api = {
coolName : privateFun1
};
return public_api;
}());
Why this works
We get the desired code modification (function wrapping), essentially in place since the variables assigned to function expressions have exactly the same scope as the original named functions themselves.
A VIM regex to help
I also created a VIM regex to help with this, at least the assignment line anyway:
s/function \(\w\+\)\(.\+\)$/var \1 = $(function \1\2/g

Advanced Javascript initialisation

I'm having trouble deciphering the following Javascript initialisation statement:
(function(NAMESPACE) {
NAMESPACE.nav = {};
var nav = NAMESPACE.nav,
_init = false,
_isNavOpen = false,
_inner = document.getElementById('inner-wrap');
// constants
nav.CLASS = 'js-nav-open';
nav.CLASS_READY = 'js-nav';
nav.CONTAINER = '#nav';
nav.DURATION = 400;
nav.HAS_CSSTRANSITIONS = $('html').hasClass('csstransitions') && $('html').hasClass('csstransforms3d');
...
...
// toggle open/close
nav.toggle = function(event) {
event.stopPropagation();
if(_isNavOpen && $('html').hasClass(nav.CLASS)) {
nav.close();
} else {
nav.open();
}
// this is for the links
if(event) {
event.preventDefault();
}
};
}(PROJECT_NAME));
It seems unnecessarily complicated - calling (or setting?) 'nav' 3 times in 2 lines. Can somebody please explain what the point is of flipping it around like this?
This is an example of a JavaScript closure which is commonly used to create private scope and avoid having the objects pollute the global scope.
It is very common to create plugins this way to avoid conflicts with other functionality on the page as a result of variables with the same name etc. Essentially it's a mechanism for managing scope.
This is a common practice when using jQuery:
(function ($) {
var div = $('#my-div');
// Etc
}(jQuery));
Wrapping your script in a closure ensures that certain variables will have the values you expect them to.
For example, jQuery uses the $ for doing just about everything. Most people like to use $('do something') rather than jQuery('do something').
But say that you have another library on the page that also uses the global variable $.
By wrapping your code in the closure, you "reserve" the $ as jQuery's, and jQuery's alone. (When you pass in jQuery as the argument to closure, $ can only mean "jQuery," in the scope of this function.)
Similarly, in your example, you are reserving the NAMESPACE variable. Even if there were another variable called NAMESPACE, causing a racket somewhere else on the page, by passing in a variable at the end of your closure, you will be guaranteed that NAMESPACE will be the object you expect it to be (at least within the closure).
Say that you had a global variable called AbominableSnowman, but you wanted to use AS as a shortcut. By doing this:
var AS = "Apple Soup";
(function (AS) {
AS.tellMeAboutSnowmen();
alert(AS.snowballs);
}(AbominableSnowman));
Your code will still function as you intended. (Proof: http://jsfiddle.net/RUzZH/1/)
As for "flipping it around," it seems like the original programmer wanted to shorten NAMESPACE.nav down to nav. This was probably the best way of doing that.
An alternative (not recommended):
// It's best to limit your assignments to 1-per-line
// This kind of code isn't fun to debug, or even read
var nav = NAMESPACE.nav = {};
It doesn't seem like something worth fretting over. However, since this script interacts with NAMESPACE.nav quite often, it will be slightly, slightly faster to directly reference the .nav property with the nav variable. (This really is a micro-optimization, but in this case it's conveniently justifiable for a different reason [sake of clarity].)
Here's a line-by-line explanation (with headers just to break it up):
Setup:
// Create an anonymous function expression taking `NAMESPACE` as a parameter.
// Likely the *real* namespace will be passed to the function at the end
// with ... })(realnamespacetomodify);
(function(NAMESPACE) {
// Create the new part of the namespace. Note that we are editing a reference
// so really this change happens on whatever object was passed in.
NAMESPACE.nav = {};
// Create a local pointing to this new sub-namespace. Probably just for
// convenience, also possibly for portability (if the name is used in closures,
// then those closures don't need to refer to NAMESPACE directly).
var nav = NAMESPACE.nav,
Module definition:
// While nav refers to an object likely in global scope, nav itself can
// never be referred to from global scope because it is a local here.
// These variables are local here. They can never be referred to by global scope.
_isNavOpen = false,
_inner = document.getElementById('inner-wrap');
// These variables, added to nav, can be accessed using the object that
// nav refers to in global scope (see the end).
nav.CLASS = 'js-nav-open';
...
// This function is also added to nav, therefore it can be accessed outside
nav.toggle = function(event) {
...
// This reference to _isNavOpen resolves because this function
// is a closure, and binds variables outside its scope
// to the function itself. So even though _isNavOpen can't be
// accessed globally, it can be accessed here, making it like
// a private member of this namespace.
if(_isNavOpen && $('html').hasClass(nav.CLASS)) {
// nav is also bound by the closure and can be accessed here
nav.close();
} ...
};
Use in global space:
}(PROJECT_NAME));
console.log(PROJECT_NAME.nav.CLASS); // "js-nav-open"
console.log(PROJECT_NAME.nav.toggle); // Function object
This is a module pattern. It is used for several reasons:
Code portability (not referring to global objects inside the module)
Scoping (avoiding assigning unnecessary vars to global namespace)
Visibility (hiding private access variables)
As for the first three lines themselves (your original question), they could refer to PROJECT_NAME directly, but it looks like it's been set up to aid code portability. You'll notice that the anonymous function itself never points to the real object (PROJECT_NAME). That means that you can copy and paste this part around and only change that reference in one place.
The other answer mentions scope, and while that's important too, it doesn't explain all benefits of this code, such as why it doesn't just directly refer to existing global variables. The scope-hiding benefits themselves are achieved with this part of the pattern:
(function() {
... // Anything set here is local, not global.
})();

Should I use window.variable or var?

We have a lot of setup JS code that defines panels, buttons, etc that will be used in many other JS files.
Typically, we do something like:
grid.js
var myGrid = .....
combos.js
var myCombo = .....
Then, in our application code, we:
application.js
function blah() {
myGrid.someMethod()
}
someother.js
function foo() {
myCombo.someMethod();
myGrid.someMethod();
}
So, should we be using the var myGrid or is better to use window.myGrid
What's the difference?
A potentially important difference in functionality is that window.myGrid can be deleted, and var myGrid can not.
var test1 = 'value';
window.test2 = 'value';
console.log( delete window.test1 ); // false ( was not deleted )
console.log( delete window.test2 ); // true ( was deleted )
console.log( test1 ); // 'value' ( still accessible )
console.log( test2 ); // ReferenceError ( no longer exists )
I would suggest creating a namespace variable var App = {};
App.myGrid = ...
That way you can limit the pollution of the global namespace.
EDIT: Regarding the number of variables issue - 2 possible solutions come to mind:
You can further namespace them by type(Grids, Buttons, etc) or by relationship(ClientInfoSection, AddressSection, etc)
You encapsulate your methods in objects that get instantiated with the components you have
ex: you have
function foo() {
myCombo.someMethod();
myGrid.someMethod();
}
becomes:
var Foo = function(combo, grid) {
var myCombo = combo;//will be a private property
this.myGrid = grid;//will be a public property
this.foo = function() {//public method
myCombo.someMethod();
myGrid.someMethod();
}
}
App.myFoo = new Foo(someCombo, someGrid);
App.myFoo.foo();
this way you limit the amount of little objects and only expose what you need (namely the foo function)
PS: if you need to expose the internal components then add them to this inside the constructor function
One nice use of window.variable is that you can check it without having a javascript error. For example, if you have:
if (myVar) {
//do work
}
and myVar is not defined anywhere on the page, you will get a javascript error. However:
if (window.myVar) {
//do work
}
gives no error, and works as one would expect.
var myVar = 'test' and window.myVar = 'test' are roughly equivalent.
Aside from that, as other said, you should descend from one global object to avoid polluting the global namespace.
In global scope the two are in fact equivalent functionality-wise. In function scope, var is certainly preferable when the behaviour of closures is desired.
I would just use var all of the time: firstly, it's consistent with the usually preferred behaviour in closures (so it's easier to move your code into a closure if you decide to do so later), and secondly, it just feels more semantic to me to say that I'm creating a variable than attaching a property of the window. But it's mostly style at this point.
The general answer to the question would be to use var.
More specifically, always put your code in an Immediately Invoked Function Expression (IIFE):
(function(){
var foo,
bar;
...code...
})();
This keeps variables like foo and bar from polluting the global namespace. Then, when you explicitly want a variable to be on the global object (typically window) you can write:
window.foo = foo;
JavaScript has functional scope, and it's really good to take full advantage of it. You wouldn't want your app to break just because some other programmer did something silly like overwrote your timer handle.
In addition to other answers, worth noting is that if you don't use var inside a function while declaring a variable, it leaks into global scope automatically making it a property of window object (or global scope).
To expand on what Liviu said, use:
App = (function() {
var exports = {};
/* code goes here, attach to exports to create Public API */
return exports;
})();
By doing that you can hide some of your implementation specific code, which you may not want exposed by using var's inside. However, you can access anything attached to the exports object.

I've Heard Global Variables Are Bad, What Alternative Solution Should I Use?

I've read all over the place that global variables are bad and alternatives should be used. In Javascript specifically, what solution should I choose.
I'm thinking of a function, that when fed two arguments (function globalVariables(Variable,Value)) looks if Variable exists in a local array and if it does set it's value to Value, else, Variable and Value are appended. If the function is called without arguments (function globalVariables()) it returns the array. Perhaps if the function is fired with just one argument (function globalVariables(Variable)) it returns the value of Variable in the array.
What do you think? I'd like to hear your alternative solutions and arguments for using global variables.
How you would use globalVariables();
function append(){
globalVariables("variable1","value1"); //globalVariables() would append variable1 to it's local array.
};
function retrieve(){
var localVariable1 = globalVariables("variable1"); //globalVariables() would return "value1".
};
function retrieveAll(){
var localVariable1 = globalVariables(); //globalVariables() would return the globalVariable()'s entire, local [persistently stored between calls] array.
};
function set(){
globalVariables("variable1","value2"); //globalVariables() would set variable1 to "value2".
};
Is this a Singleton Pattern BTW?
In this specific scenario a function may set a variable at one point in time, and much later another function, maybe when a user submits a form, will need to get that variable. Therefore the first function couldn't pass the variable as an argument to the later function as it would never be called from the first.
Thank you, I appreciate all your help!
The primary reason why global variables are discouraged in javascript is because, in javascript all code share a single global namespace, also javascript has implied global variables ie. variables which are not explicitly declared in local scope are automatically added to global namespace. Relying too much on global variables can result in collisions between various scripts on the same page (read Douglas Crockford's articles).
One way to reduce global variables is to use the YUI module pattern. The basic idea is to wrap all your code in a function that returns an object which contains functions that needs to be accessed outside your module and assign the return value to a single global variable.
var FOO = (function() {
var my_var = 10; //shared variable available only inside your module
function bar() { // this function not available outside your module
alert(my_var); // this function can access my_var
}
return {
a_func: function() {
alert(my_var); // this function can access my_var
},
b_func: function() {
alert(my_var); // this function can also access my_var
}
};
})();
now to use functions in your module elsewhere, use FOO.a_func(). This way to resolve global namespace conflicts you only need to change the name of FOO.
Semantics my boy. Semantics.
Start with one global: myApp = {};
Everything should be in that. The only exception would be your AJAX library (there are some extreme exceptions like working with JSONP callbacks).
There should be very few properties in myApp. You'll want to hold your application properties in containers such as config or settings.
myApp = {
config:{
prop:1
},
settings:{
prop:2
},
widgets:{
List: function(props){},
Item: function(props){}
}
}
Then you may have more properties in lower modules, components, singletons and Class constructors (widgets).
This setup gives you the added benefit of being able to access any property from any other location since you can get it with the myApp global. However, you should use "this" whenever possible because the lookup is faster. And just set the property directly, don't bother with the pseudo getter/setter stuff. If you really need a getter/setter, code it for that specific use.
The reason your example doesn't work is it's too generic and you seem to be looking for an excuse to work in the global space.
And don't get clever with private variables. They're bad too:
http://clubajax.org/javascript-private-variables-are-evil/
Global state causes problems in several areas. One is code reuse. When you access some global state that means the component must be aware of it's environment(something outside of itself). You should avoid this as much as possible, because it makes the component unpredictable.
Say I have an object that accesses your globalVariables function and I want to use it in another page. How do I know to define the globalVariables object or even how to define it? However if you can pass the information into a constructor or as an argument to a function then I can easily determine what is required by the object.
Also when you access or modify the global scope then you risk affecting other objects. This is why libraries like jquery use only a single name on the global scope(the least possible). It lessens the possibility of conflict with other libraries. In other words the global scope is out of your control, so it is dangerous.
Using global variables is generaly speaking a bad practice, regardless of the language of choice. They are not even (easily) allowed to use when at strict mode, which I highly recommend.
Consider this piece of code I found:
if (typeof session != 'undefined' && !data.cart.request_status)
data.input_definitions.passengers =
inflate_passenger(session, data.input_definitions.passengers);
I needed to turn around and ask a felow programmer where did this session variable came from, as no code search showed up where was set.
I turned out another package from the company sets the global variable.
Code it's like a joke: if you need to explain it it's probably not that good.
Workaround using ES6:
If at Node, use import or require to bring the desired stuff into lexical scope, don't let people touch your global environment without you knowing it.
import {Sesssion} from 'api-core';
const Session = require('api-core').session;
If you are at the frontend delivering code for the browser you can't use import unless you transpile your ES6 code using Babel.
Example transpiling using Gulp.js:
// $ npm install --save-dev gulp-babel babel-preset-es2015
// gulpfile.js
const gulp = require('gulp');
const babel = require('gulp-babel');
gulp.task('transpile', () => {
return gulp.src('src/app.js')
.pipe(babel({presets: ['es2015']}))
.pipe(gulp.dest('dist'));
});
// $ gulp transpile
Legacy workaround:
When using ES6 features is not an option the only workaround to using a bunch of global variables, is using only one, and have hope:
// scripts/app.js
var MyApp = {
globals: {
foo: "bar",
fizz: "buzz"
}
};
var ASHIVA_HandsOffNHS = (function() {
// VARIABLES
var my_var = 10;
// PRIVATE FUNCTIONS
function bar() {
console.log(my_var + 5);
}
// PUBLIC OBJECT
myObject = {};
myObject['a_func'] = function() {
my_var += 10;
console.log(my_var);
};
myObject['b_func'] = function() {
my_var = 0;
console.log(my_var);
};
return myObject;
})();
ASHIVA_HandsOffNHS.a_func();
ASHIVA_HandsOffNHS.b_func();
ASHIVA_HandsOffNHS.a_func();
The issue with your solution is that it just makes you code harder to understand while still keeping all the downsides of global variables. The page you linked to covers the problems. The only problem your proposed solution really solves is namespace pollution but at the cost of not being able to see what global variables are declared as easily as the declaration is a function call).
The solution is to write code without global variables. If a function needs a value pass it as a argument.
You really don't want to do this.
As to why see e.g. the top post here: What is the most EVIL code you have ever seen in a production enterprise environment?
As a side note, one can always execute "global" code without littering the place with globals:
(function() {
var notaglobal = 1;
alert(notaglobal);
})();
//notaglobal is not defined in this scope
Other answer most explain with anonymous function as this article mention,
Anonymous functions are difficult to debug, maintain, test, or reuse.
Here are example with normal function. It's easier to read and understand.
/* global variable example */
var a= 3, b= 6;
function fwithglobal(){
console.log(a, b); // 3 6 expected
}
fwithglobal(); // first call
function swithglobal(){
var a=9;
console.log(a, b); // not 3 6 but 9 6
}
swithglobal(); // second call
/* global variable alternative(function parameter) */
function altern(){
var a= 3, b= 6; // var keyword needed
f_func(a,b);
s_func(a,b);
}
function f_func(n, m){
console.log(n, m); // 3 6 expected
}
function s_func(n, m){
var a=9;
console.log(n, m); // 3 6 expected
}
altern(); // only once
Global variables are bad... if left unmanaged!
The potential risks of global variables is as high as the pleasure and productivity gains of having frequently used objects ready to use.
I don't believe one should seek a single alternative. Instead I advocate for one object in charge of managing those globals and as the code base/component matures, refactor them out
One thing not mentioned in the current answers which I think is critical is an understanding of DI and IoC containers. These address many of the problems people try to solve with global variables, but covering related concerns that plain globals can't, like object life cycles.

Categories

Resources