Have questions? Discuss this HTML tutorial with others on the forums.
Each variable you declare has a certain level of visibility that determines when you can actually use it. Much of what I will cover here should be pretty straightforward, but JavaScript does have its quirks that you should keep in mind.
Variables
In JavaScript, you can use variables by explicitly declaring them by using the var keyword:
- var foo = "hello";
- // or
- var bar;
- bar = "hello";
You don't have to explicitly declare your variables though. You could get away with just doing the following:
- zorb = "good bye";
In the above case, the zorb variable is declared and used without explicitly using the var variable.
Global Scope
Let's start with our exploration of scope by looking at what happens when something is declared at a global level:
- <script>
- var counter = 0;
- </script>
A global variable is something that can be accessed from anywhere in your current document.
This means, you can access this variable from anywhere in your current script region:
- <script>
- var counter = 0;
- function returnCount()
- {
- return counter;
- }
- </script>
You can even access a global variable across different script elements as long as the script regions are in the same document:
- <script>
- var counter = 0;
- function returnCount() {
- return counter;
- }
- </script>
- <script>
- alert(counter); // returns 0
- </script>
When something is considered global in JavaScript, what we technically mean is that it is a direct child of your browser's window object.
In our example, counter and window.counter point to exactly the same thing:
- alert(window.counter == counter);
Realizing that global variables live under your window object should help you understand why you can access a global variable from anywhere in your document.
Inside Functions
Functions are interesting because you will start to see scope coming into play. As you saw earlier, a variable declared globally obviously works inside a function:
- <script>
- var counter = 0;
- function returnCount() {
- return counter;
- }
- </script>
A variable declared inside a function will not work when accessed outside of it, though:
- <script>
- function setState() {
- var state = "on";
- }
- setState();
- alert(state) // undefined
- </script>
The state variable is declared inside my setState function, and accessing the state variable outside of that function doesn't work.
There is an exception to this though. Notice that I explicitly declared my state variable by using the var keyword.
If I declare the state variable without using the var keyword, the scoping behavior is drastically different:
- <script>
- function setState() {
- state = "on";
- }
- setState();
- alert(state) // "on"
- </script>
In this case, even though your state variable makes its appearance inside the setState function first, not including the var keyword makes this variable live globally on your window object.
Any time, a variable that is used without being declared using the var keyword will always live globally.
The last case involving functions is when a variable is passed in as an argument to a function:
- <script>
- var state = "off";
- function setState(s) {
- s = "on";
- alert(s); // on
- }
- setState(state);
- alert(state); // off
- </script>
In this case, we have state declared as a global variable, and it is passed in to our setState function. The setState function takes the passed in variable and changes its value to something else.
Despite the setState function changing the value of the passed in variable, the original state variable still refers to its original value. The reason is that a variable passed in to a function lives inside the scope of that function only.
Block Scoping
The next area we will look at is what happens to variables when they are declared inside a block such as if, for, while, etc:
- <script>
- function setState(choice) {
- if (choice == true) {
- var color = "green";
- } else {
- var color = "blue";
- }
- alert(color); // returns blue (?!!)
- }
- setState(false);
- </script>
Notice that the color variables are being declared inside our if statement. You may think that because the variable is declared explicitly with a var inside the if block, the variable should not usable outside of it.
As you can see, that is not the case. JavaScript does not support block-level scoping. This means that your color variable is accessible to your entire setState function!
Scoping and Prototypes
When working with objects, you can choose to extend them with your own functions by using the prototype property.
Here is a straightforward example:
- <script>
- function BlueCircle() {
- this.radius = 4;
- this.color = "blue";
- }
- BlueCircle.prototype.setColor = function (newColor) {
- this.color = newColor;
- }
- BlueCircle.prototype.getColor = function () {
- return (this.color);
- }
- var circle = new BlueCircle();
- circle.setColor("aqua");
- alert(circle.getColor()); // aqua
- </script>
When I initialize the BlueCircle object, the value of color in the BlueCircle is set to blue. When I call the setColor method, I pass in a new value that overrides the earlier color value with the new one.
The behavior is different when you decide to set the property of the object via the prototype though:
- <script>
- function BlueCircle() {
- this.radius = 4;
- this.color = "blue";
- }
- BlueCircle.prototype.setColor = function (newColor) {
- this.color = newColor;
- }
- BlueCircle.prototype.getColor = function () {
- return (this.color);
- }
- BlueCircle.prototype.radius = 10;
- var circle = new BlueCircle();
- alert(circle.radius);
- </script>
In this example, I try to override the BlueCircle constructor's radius property by using the prototype property:
- BlueCircle.prototype.radius = 10;
Given what you saw earlier, you may think that your radius value now is going to be 10 when accessed via our BlueCircle object. The result is that it actually remains at its original value of 4.
Why? The reason is that a property declared via an object's prototype takes lower precedence than a property declared directly on the object.
If I declare a new property via the prototype that isn't already declared in my constructor, then I can access that property via my object as expected:
- <script>
- function BlueCircle() {
- this.radius = 4;
- this.color = "blue";
- }
- BlueCircle.prototype.setColor = function (newColor) {
- this.color = newColor;
- }
- BlueCircle.prototype.getColor = function () {
- return (this.color);
- }
- BlueCircle.prototype.radius = 10;
- BlueCircle.prototype.speed = 5;
- var circle = new BlueCircle();
- alert(circle.speed); // returns 5
- </script>
The reason this works is that the speed variable doesn't exist in the constructor. This means the earlier precedence issue doesn't apply because there is no equivalent speed variable that takes priority in our object!
Closures
Closures are an interesting topic of their own, so I will cover that in detail in a later tutorial. Stay tuned.
Conclusion
Well, that concludes this topic of variable scopes. This topic seems very simple on the surface, but as you can see, there are some unique characteristics that takes some time and practice to fully understand.
Need Help?
If you have questions, need some assistance on this topic, or just want to
chat - please drop by our friendly forums
and post your question. There are a lot of knowledgeable and witty people who
would be happy to help you out. Plus, we have a
large collection of smileys
you can use
![]()
Share
Did you enjoy reading this and found it useful? If so, please share it with your friends:
If you didn't like it, I always like to hear how I can do better next time. Please feel free to contact me directly at kirupa[at]kirupa.com.
Cheers!
|











