views:

149

answers:

2

I've noticed all over the place people mention "Just define a variable in the top of your JS code and it becomes global" in response to questions like, "How do I create a global variable from inside a function?". Most of the answers start by saying it isn't possible to achieve that. Of course it is possible to do this:

<script type="text/javascript">
    window.spam = 'Hello World';
</script>

Then, later in your code, you can say:

<script type="text/javascript">
    alert(spam);
</script>

This works perfectly fine in IE6+, Firefox, Chrome, Safari, etc. So why does nobody do this?

In my case I want people to access a global variable called fooBar from anywhere in their code and in my AJAX library, I want the variable to update behind the scenes automatically so that when they say $.do_some_magic() they can be sure that fooBar will reflect the changes made by $.do_some_magic() without having to think about it. I don't want them to have to create the variable up high in their code and I don't want to create the variable up high in my library code either. I suppose I just hate defining global variables at the top and would rather not unless there is a good reason not to. Is there?

+6  A: 

Clarity

Its an explicit way of showing that you meant to create a global variable.

// Unclear: Intentional, or accident
function privateScope() {
  spam = "hello";

  function globalFunction() {

  }
}

That will make a variable global simply because it was declared that way, though it is not immediately obvious the programmer intended the variable and the function to have a global scope.

// Clear: Intentional global use
function privateScope() {
  window.spam = "hello";

  window.globalFunction = function () {

  }
}

This example is more obvious.

Best Practice

If you know ahead of time a variable will be used with the global scope, it should be declared at the top of your file, outside all your functions:

var spam;

If you are inside a self executing anonymous function, then explicitly use window.spam:

(function(){
    // currently private to this scope
    var spam;

    ... lots of code ...

    // Expose the variable publically
    window.spam = spam;
})();

Name Collision

anthares brought up the other side of this, which is name collision

A number of libraries expose a single top level object. You could either construct a function to do this, or use a simple object literal as a namespace:

(function(){
   // Expose a single top level variable
   window.YourCompany = { };

   // Private:
   var spam = "name";

   ... other code ...


   // Make public
   window.YourCompany.spam = spam;

})();
Doug Neiner
+2  A: 

Sure, you can say window.spam. But you would only need to if you had also defined a local variable called spam. Otherwise just saying spam automatically refers to the global variable.

It's bad practice to refer to a global variable you haven't declared with var, but it'll work unless you use ECMAScript Fifth Edition ‘strict mode’.

Because var declarations are ‘hoisted’ and processed before code, there is no reason you have to define your globals “at the top”. This is perfectly valid even in strict mode:

function setFooTo6() {
    fooBar= 6;
}

var fooBar;

although I'd hesitate to do that as it's not entirely clear.

bobince
Ah, I did not know that.
orokusaki
@bobince I didn't know that either, though I agree it might not be clear.
Doug Neiner