Every building needs strong foundation to build on. Understanding variable scope in JavaScript is one of the keys to building a solid foundation. This article will explain how JavaScript's scoping system works. We'll also cover a related topic known as hoisting.
Variable Scope
To work with JavaScript efficiently, one of the first things you need to understand is the concept of variable scope. The scope of a variable is controlled by the location of the variable declaration, and defines the part of the program where a particular variable is accessible.
Scoping rules vary from language to language. JavaScript has two scopes - global and local. Any variable declared outside of a function belongs to the global scope, and is therefore accessible from anywhere in your code. Each function has its own scope, and any variable declared within that function is only accessible from that function and any nested functions. Because local scope in JavaScript is created by functions, it's also called function scope. When we put a function inside another function, then we create nested scope.
Currently, JavaScript, unlike many other languages, does not support block level scoping. This means that declaring a variable inside of a block structure like a for
loop, does not restrict that variable to the loop. Instead, the variable will be accessible from the entire function. It's worth noting that the upcoming ECMAScript 6 will support block level scopes via the let
keyword.
To make things clear let's use a simple metaphor. Every country in our world has frontiers. Everything inside these frontiers belongs to the country's scope. In every country there are many cities, and each one of them has its own city's scope. The countries and cities are just like JavaScript functions - they have their local scopes. The same is true for the continents. Although they are huge in size they also can be defined as locales. On the other hand, the world's oceans can't be defined as having local scope, because it actually wraps all local objects - continents, countries, and cities - and thus, its scope is defined as global. Let's visualize this in the next example:
[js] var locales = { europe: function() { // The Europe continent's local scope var myFriend = "Monique"; var france = function() { // The France country's local scope var paris = function() { // The Paris city's local scope console.log(myFriend); }; paris(); }; france(); } }; locales.europe(); [/js]
Now that we understand what local and global scopes are, and how they are created, it's time to learn how the JavaScript interpreter uses them to find a particular variable.
Back to the given metaphor, let's say I want to find a friend of mine whose name is Monique. I know that she lives in Paris, so I start my searching from there. When I can't find her in Paris I go one level up and expand my searching in all of France. But again, she is not there. Next, I expand my searching again by going another level up. Finally, I found her in Italy, which in our case is the local scope of Europe.
In the previous example my friend Monique is represented by the variable myFriend
. In the last line we call the europe()
function, which calls france()
, and finally when the paris()
function is called, the searching begins. The JavaScript interpreter works from the currently executing scope and works it way out until it finds the variable in question. If the variable is not found in any scope, then an exception is thrown.
This type of look up is called lexical (static) scope. The static structure of a program determines the variable scope. The scope of a variable is defined by its location within the source code, and nested functions have access to variables declared in their outer scope. No matter where a function is called from, or even how it's called, its lexical scope depends only by where the function was declared.
In JavaScript, variables with the same name can be specified at multiple layers of nested scope. In such case local variables gain priority over global variables. If you declare a local variable and a global variable with the same name, the local variable will take precedence when you use it inside a function. This type of behavior is called shadowing. Simply put, the inner variable shadows the outer.
That's the exact mechanism used when a JavaScript interpreter is trying to find a particular variable. It starts at the innermost scope being executed at the time, and continue until the first match is found, no matter whether there are other variables with the same name in the outer levels or not. Let's see an example:
Read more on SitePoint...
Continue reading %Demystifying JavaScript Variable Scope and Hoisting%
by Ivaylo Gerchev via SitePoint