By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,853 Members | 1,012 Online
Bytes IT Community
Submit an Article
Got Smarts?
Share your bits of IT knowledge by writing an article on Bytes.

Variable Scope in JavaScript

pbmods
Expert 5K+
P: 5,821
VARIABLE SCOPE IN JAVASCRIPT
LEVEL: BEGINNER/INTERMEDIATE (INTERMEDIATE STUFF IN [BRACKETS])
PREREQS: VARIABLES

First off, what the heck is 'scope' (the kind that doesn't help kill the germs that cause bad breath)? Scope describes the context in which a variable can be used. For example, if a variable's scope is a certain function, then that variable can only be used in that function. If you were to try to access that variable anywhere else in your script, it would come back as undefined.

There are four (technically three) types of scope in javascript:
  • window - These variables can be used anywhere in your script at any time.
  • function - These variables are only available inside of a particular function.
  • class (arguably same as function) - These variables are only available to members of a particular class.
  • block (new in JavaScript 1.7) - These variables only exist within a particular code block (i.e., between a set of '{' and '}').

WINDOW SCOPE

Window-level variables get attached to the universal window object in your script. To declare a window-level (or "global") variable, you would use this syntax:

Expand|Select|Wrap|Line Numbers
  1. <script type="text/javascript">
  2.     var myGlobal = "This is a global variable because it's not declared inside a function.";
  3.  
  4.     myGlobal = "This is also a global variable because it is not defined using the 'var' keyword.  See below for more info.";
  5.     window.myGlobal = 'This is also global for the same reason the previous statement is global.';
  6. </script>
  7.  
The var keyword binds a variable to its parent context. If you declare a variable using the var keyword outside of a function or object, it is global, since the default context is window.

So:

Expand|Select|Wrap|Line Numbers
  1. var myGlobal = 'This is global because my context is window, but...';
  2.  
  3. function doSomething() {
  4.     var myLocal = '... this is not because my context is doSomething, not window.';
  5. }
  6.  
If you don't use the var keyword, the browser will also automatically make your variable global. The reason why this happens is the same reason why you can use e.g., 'location.href' instead of 'window.location.href'.

[INTERMEDIATE STUFF: JavaScript has a (little-used) 'with' keyword that allows you to arbitrarily define a context. When you define a context using the with keyword, you are allowed to omit the parent object when you access its members.

For example:

Expand|Select|Wrap|Line Numbers
  1. var myObject = {
  2.     product:    'paper',
  3.     quantity:    500,
  4.     salesman:    'Fred'
  5. };
  6.  
  7. with(myObject) {
  8.     alert(salesman);
  9. }
  10.  
The above code will alert 'Fred'.

Similarly, every script in JavaScript starts with the following (implied) statement:

Expand|Select|Wrap|Line Numbers
  1. with(window) {
  2.     //    Your code goes here.
  3. }
  4.  
Proper usage of the 'with' keyword (and also why it's almost never used) is available here.]


Just like the way these two statements are identical:

Expand|Select|Wrap|Line Numbers
  1. window.location.href = 'http://www.example.com/';
  2. location.href = 'http://www.example.com/';
  3.  
So are these statements identical:

Expand|Select|Wrap|Line Numbers
  1. window.myVar = 'Global variable!';
  2. myVar = 'Also global!';
  3.  
Incidentally, since there's only one instance of window per browser window (or tab), any script that you include in your page can access any global variable. Global variables are not limited to individual <SCRIPT> blocks, and you can even declare a global variable in one .js file and access it in another (though you might want to check to make sure it exsts first)!

FUNCTION / CLASS SCOPE

[INTERMEDIATE STUFF: I've lumped function and class together since classes are basically just really, really shiny functions in JavaScript.]

This is where the var keyword really becomes important. Remember from the 'window scope' section that the var keyword will bind a variable to its parent context:

Expand|Select|Wrap|Line Numbers
  1. <script type="text/javascript">
  2. var myGlobal = 'Global because my context is window.';
  3.  
  4. function doSomething() {
  5.     var myLocal = 'Not global because my context is doSomething, not window.';
  6. }
  7. </script>
  8.  
Since we're using var to declare the variable 'myLocal' inside of doSomething, we are binding myLocal to doSomething's context. In other words:

Expand|Select|Wrap|Line Numbers
  1. function doSomething() {
  2.     var myLocal = 'Not a global variable.';
  3.  
  4.     alert(myLocal);
  5. }
  6.  
  7. doSomething();    //    Alerts 'Not a global variable.'.
  8. alert(myLocal);    //    Alerts 'undefined'.
  9.  
If we wanted to make myLocal global, we could simply remove the var keyword:

Expand|Select|Wrap|Line Numbers
  1. function doSomething() {
  2.     myLocal = 'This is global because it gets attached to window.';
  3.  
  4.     alert(myLocal);
  5. }
  6.  
  7. doSomething();    //    Alerts 'This is global because it gets attached to window.'.
  8. alert(myLocal);    //    Alerts 'This is global because it gets attached to window.'.
  9.  
[INTERMEDIATE STUFF: Similarly, you would use the var keyword to bind local variables to your class's context. This is, incidentally, how you implement private variables in JavaScript classes:

Expand|Select|Wrap|Line Numbers
  1. function Class() {
  2.     var myPrivate;
  3.  
  4.     function __construct() {
  5.         myPrivate = 'A private variable.';
  6.         alert(myPrivate);
  7.     }
  8.  
  9.     __construct();
  10. }
  11.  
  12. var myObject = new Class();    //    Alerts 'A private variable.'.
  13. alert(myObject.myPrivate);    //    Alerts 'undefined' because myPrivate is not a member of myObject.
  14.  
Why does this work? See 'Scope Inheritance' below.]


BLOCK SCOPE (NEW IN JAVASCRIPT 1.7)

New in JavaScript 1.7 (getting the idea?) is the let keyword. let allows you to scope a variable to a specific block of code.

For example:

Expand|Select|Wrap|Line Numbers
  1. let(myVar = 5) {
  2.     alert(myVar);    //    Alerts 5.
  3. }
  4.  
  5. alert(myVar);        //    Alerts 'undefined'.
  6.  
Since JavaScript 1.7 isn't supported all browsers yet, it is recommended that you not use the let keyword just yet. But it's fun to know about!

For more information on JavaScript 1.7, check out this document.

SCOPE INHERITANCE

So we know that you can use scoping to limit access to a variable to a specific context. But what about functions (contexts) inside of functions or classes? How does scoping work then?

Let's look at a sample setup:

Expand|Select|Wrap|Line Numbers
  1. function myOuterFunction() {
  2.     var myLocal = 'Declared locally.';
  3.  
  4.     function myInnerFunction() {
  5.         alert(myLocal);
  6.     }
  7.  
  8.     myInnerFunction();    //    Alerts 'Declared locally.'
  9. }
  10.  
  11. myOuterFunction();        //    To declare myInnerFunction...
  12. myInnerFunction();        //    Generates an error (see below).
  13.  
Note that in the example above, since myInnerFunction is declared inside of myOuterFunction, it has access to all of myOuterFunction's variables.

[INTERMEDIATE STUFF: Note also that myInnerFunction is attached to myOuterFunction's context. In other words, if you try to call myInnerFunction outside of myOuterFunction, you'll get an error.

The reason for this is the same reason why the myLocal variable is undefined outside of myOuterFunction. For more information, take a look at this article.]


HANDLING COLLISIONS

What happens if you have two variables in overlapping contexts with identical names?

Expand|Select|Wrap|Line Numbers
  1. var myVar = 'Global';
  2.  
  3. alert(myVar);    //    Alerts 'Global'.
  4.  
  5. function myOuterFunction() {
  6.     var myVar = 'Local';
  7.     alert(myVar);    //    Alerts 'Local'.
  8.  
  9.     function myInnerFunction(myVar) {
  10.         myVar = myVar + '!';
  11.         alert(myVar);
  12.     }
  13.  
  14.     myInnerFunction('Inner');    //    Alerts 'Inner!'.
  15. }
  16.  
  17. myOuterFunction();    //    Do we modify myVar?
  18. alert(myVar);        //    Alerts 'Global'.
  19.  
When you declare a variable inside of a given context, that variable will supersede any other available variables with that name. It doesn't overwrite them; it merely uses the local variable instead of the global (or parent) one.

This is why the final alert statement in the above example outputs 'Global' instead of 'Inner!'. We're not actually changing the value of window.myVar. Instead we're setting it aside and creating a new variable named myVar inside of myInnerFunction and modifying that variable instead.

Note also that when you declare a function, you are also *declaring* its arguments. So in this line:

Expand|Select|Wrap|Line Numbers
  1.     function myInnerFunction(myVar) {
  2.  
You are actually declaring a variable named myVar and attaching it to myInnerFunction's context. You are *not* implicitly using the value of the myVar variable that you declared in myOuterFunction or the global myVar. It would produce the same result as if you did this instead:

Expand|Select|Wrap|Line Numbers
  1.     function myInnerFunction(someOtherVar) {
  2.  
CONCLUSION

So now you know the basics [and intermediates] behind variable scope in JavaScript. JavaScript variables [and functions, classes and objects] can have one of four [technically three] different scopes, depending on how -- and in what context -- they are declared:
  • window (or 'global') scope - Available to any script anywhere in the window once declared.
  • function scope - Available only to functions and objects inside of the function that defined the variable.
  • class scope - Available only to functions and objects inside of the class that defined the variable.
  • block scope - Available only to functions and objects inside of the block created by using a let statement.

That concludes today's lesson on variable scope. Live long and write prosperous code!
May 31 '07 #1
Share this Article
Share on Google+
1 Comment


iam_clint
Expert 100+
P: 1,208
nice read, good article :)
Jul 26 '07 #2