80

I've heard from a variety of places that global variables are inherently nasty and evil, but when doing some non-object oriented Javascript, I can't see how to avoid them. Say I have a function which generates a number using a complex algorithm using random numbers and stuff, but I need to keep using that particular number in some other function which is a callback or something and so can't be part of the same function.

If the originally generated number is a local variable, it won't be accessible from, there. If the functions were object methods, I could make the number a property but they're not and it seems somewhat overcomplicated to change the whole program structure to do this. Is a global variable really so bad?

Andreas Grech
  • 105,982
  • 98
  • 297
  • 360

10 Answers10

91

I think your best bet here may be to define a single global-scoped variable, and dumping your variables there:

var MyApp = {}; // Globally scoped object

function foo(){
    MyApp.color = 'green';
}

function bar(){
    alert(MyApp.color); // Alerts 'green'
} 

No one should yell at you for doing something like the above.

Kenan Banks
  • 207,056
  • 34
  • 155
  • 173
64

To make a variable calculated in function A visible in function B, you have three choices:

  • make it a global,
  • make it an object property, or
  • pass it as a parameter when calling B from A.

If your program is fairly small then globals are not so bad. Otherwise I would consider using the third method:

function A()
{
    var rand_num = calculate_random_number();
    B(rand_num);
}

function B(r)
{
    use_rand_num(r);
}
Paul Stephenson
  • 67,682
  • 9
  • 49
  • 51
  • 4
    do not pollute the global namespace! your worst case fallback should be no more than creating an object property using a single custom global object – annakata Jan 02 '09 at 15:59
  • a 4th option I came up with, when all 3 of those didn't work for me. http://stackoverflow.com/questions/3531080/how-to-get-a-variable-returned-across-multiple-functions-javascript-jquery (see answer by Emile) – Kyle Cureau Aug 22 '10 at 05:16
  • ps. pm on the link above, look for an unchecked answer by "Emile" – Kyle Cureau Aug 22 '10 at 07:51
  • I understand that this is quite old, but I was just wondering, wouldn't extensive use of the third method in a large program result in spaghetti code? – Aryan poonacha Jan 21 '17 at 09:55
  • so this is currying? been trying to get my head around that for a while and this is a really simple example – Pixelomo Jun 22 '17 at 15:31
16

Consider using namespaces:

(function() {
    var local_var = 'foo';
    global_var = 'bar'; // this.global_var and window.global_var also work

    function local_function() {}
    global_function = function() {};
})();

Both local_function and global_function have access to all local and global variables.

Edit: Another common pattern:

var ns = (function() {
    // local stuff
    function foo() {}
    function bar() {}
    function baz() {} // this one stays invisible

    // stuff visible in namespace object
    return {
        foo : foo,
        bar : bar
    };
})();

The returned properties can now be accessed via the namespace object, e.g. ns.foo, while still retaining access to local definitions.

Christoph
  • 164,997
  • 36
  • 182
  • 240
  • super awesome answer! finally a class-like structure like in other language :) – Aesthetic Sep 14 '16 at 15:37
  • This is great, this should be the accepted answer. The second pattern is apparently called "static namespacing with the object pattern" as discussed at: https://javascriptweblog.wordpress.com/2010/12/07/namespacing-in-javascript/ – suprjami Dec 19 '17 at 04:14
10

What you're looking for is technically known as currying.

function getMyCallback(randomValue)
{
    return function(otherParam)
    {
        return randomValue * otherParam //or whatever it is you are doing.
    }

}

var myCallback = getMyCallBack(getRand())

alert(myCallBack(1));
alert(myCallBack(2));

The above isn't exactly a curried function but it achieves the result of maintaining an existing value without adding variables to the global namespace or requiring some other object repository for it.

AnthonyWJones
  • 187,081
  • 35
  • 232
  • 306
  • -1. Not only is this not an example of currying, it's way too complicated an answer for the problem. – Kenan Banks Jan 02 '09 at 15:34
  • 6
    @triptych: I disagree. this is a perfectly valid and interesting solution to this kind of problem, and is exactly currying (http://www.dustindiaz.com/javascript-curry/) – annakata Jan 02 '09 at 15:57
  • +1 confusing... then enlightening! Once I saw clearly that `myCallback` is a reference to the function that `getMyCallback` returns with the `randomValue` already set. The use of `getRand` is instructive too because I see that `myCallBack(1)` called numerous times will return the same value so `myCallback` equals what is returned from `getMyCallBack(getRand())` and isn't just a reference to the function itself. It helped just to say it out loud :) – wunth Sep 19 '17 at 02:53
5

I found this to be extremely helpful in relation to the original question:

Return the value you wish to use in functionOne, then call functionOne within functionTwo, then place the result into a fresh var and reference this new var within functionTwo. This should enable you to use the var declared in functionOne, within functionTwo.

function functionOne() {
  var variableThree = 3;
  return variableThree;
}

function functionTwo() {
  var variableOne = 1;
  var var3 = functionOne();

  var result = var3 - variableOne;

  console.log(variableOne);
  console.log(var3);
  console.log('functional result: ' + result);
}

functionTwo();
gav_aus_web
  • 189
  • 3
  • 14
4

If another function needs to use a variable you pass it to the function as an argument.

Also global variables are not inherently nasty and evil. As long as they are used properly there is no problem with them.

Adam Peck
  • 6,930
  • 3
  • 23
  • 27
3

If there's a chance that you will reuse this code, then I would probably make the effort to go with an object-oriented perspective. Using the global namespace can be dangerous -- you run the risk of hard to find bugs due to variable names that get reused. Typically I start by using an object-oriented approach for anything more than a simple callback so that I don't have to do the re-write thing. Any time that you have a group of related functions in javascript, I think, it's a candidate for an object-oriented approach.

tvanfosson
  • 524,688
  • 99
  • 697
  • 795
2

Another approach is one that I picked up from a Douglas Crockford forum post(http://bytes.com/topic/javascript/answers/512361-array-objects). Here it is...

Douglas Crockford wrote:

Jul 15 '06

"If you want to retrieve objects by id, then you should use an object, not an array. Since functions are also objects, you could store the members in the function itself."

function objFacility(id, name, adr, city, state, zip) {

    return objFacility[id] = {

        id: id,
        name: name,
        adr: adr,
        city: city,
        state: state,
        zip: zip

    }
}

objFacility('wlevine', 'Levine', '23 Skid Row', 'Springfield', 'Il', 10010);

"The object can be obtained with"

objFacility.wlevine

The objects properties are now accessable from within any other function.

Joel Erenberg
  • 81
  • 2
  • 3
1

You can completely control the execution of javascript functions (and pass variables between them) using custom jQuery events....I was told that this wasn't possible all over these forums, but I got something working that does exactly that (even using an ajax call).

Here's the answer (IMPORTANT: it's not the checked answer but rather the answer by me "Emile"):

How to get a variable returned across multiple functions - Javascript/jQuery

Community
  • 1
  • 1
Kyle Cureau
  • 19,028
  • 23
  • 75
  • 104
1

I don't know specifics of your issue, but if the function needs the value then it can be a parameter passed through the call.

Globals are considered bad because globals state and multiple modifiers can create hard to follow code and strange errors. To many actors fiddling with something can create chaos.

Arthur Thomas
  • 5,088
  • 1
  • 25
  • 31