Introduction
Javascript is one of the most used languages in Web Development. For most of the developers its most confusing and complecated too, specifically for those who belong to the community of developers having strong knowledge on Object Oriented Languages like C++, Java, C# etc. This is because it has its own features and behaviors. So, here we will be looking into one of such differences, that usually creates confusion.
Background
Lets have a look into a simple examples:
Code 1.
var name = 'Ramesh';
function showName() {
console.log(name);
}
showName();
Now, lets make a little change:
Code 2.
function showName() {
if(!name) {
var name = 'Suresh';
}
console.log(name);
}
showName();
What's the output here? Few of us may say 'name
is not declared before using it, so this will give an error', and few may be right and wil say - 'It's Suresh'. And, the output is 'Suresh'.
Let's make one more change:
Code 3.
var name = 'Ramesh';
function showName() {
if(!name) {
var name = 'Suresh';
}
console.log(name);
}
showName();
So, now let's guess the output. And, if we follow our knowledge in C, C++, C#, Java we will end up saying "Ramesh". But, the output is "Suresh".
Let's see how did it happen. There are basically two things behind this output, one is Hoisting and second the Scope. So, before explaing about hoisting let's first have a look into Scopes.
A little bit about Scope
In the above code, we say the output as 'Ramesh', analyzing the code with C like syntax in mind. So, most of us guess- " As name is declared as global variable and inside 'if block' when we redefine name, its scope gets destroyed and console.log()
outputs the value of global one".
But, the fact is Javascript doesn't follow block level scoping, like C. It follows function level scope. So, whenever a new function is declared an new scope context is generated and whatever is declared inside the function, gets a new scope. This makes the concept of private in javascript.
If we define a variable with var
keyword inside a function that gives it a local scope, and it is private and local to the function. And so, being local to the function, value contained in name is 'Suresh'. And, console.log()
outputs it as 'Suresh'.
So, we talked about Scopes. But, suddenly a question strikes in our mind, Is the same global variable 'name
' is getting modified or is it a new variable? Let's check that too..
We added a line to log after showName()
in Code 3.
Code 4.
function showName() {
}
showName();
console.log(name);
And, we see that the later console.log()
gives us the Global value. So, we can say that the global is not getting affected by the local variable.
But, still few of us have confusion. If both 'name
' variables are different, why didn't get any error in Code 2? We haven't declared the variable name, and we are trying to evaluate with if. Even then it gives output without error. And, here needs the explanation for hoisting.
Hoisting in Javascript
In javascript, every variable declaration is hoisted to the top of its declaration context. So, in Code 2 and Code 3, the inner variable name is hoisted to the top of its declaration context i.e. at the top inside function's block. And, in javascript it would be treated like -
Code 5.
var name = "Ramesh";
function showName() {
var name = undefined;
if(!name) {
name = "Suresh";
}
console.log(name);
}
showName();
Here we have to keep in mind that only declaration is hoisted and initialization is done at its own place. As we see here, only variable 'name
' is hoisted up with initializing its value to 'undefined
'. So, it is 'undefined
', and as its local to the function scope it is different that the global one. Now, when we check the 'name
' variable, it is found to be undefined and then gets initialized with "Suresh" and we get the output as Suresh.
Good practices
We can avoid these types of situation by using "strict" mode. This has been introduced in ECMA-5 and is now treated as a best practice to avoid these type of situation. Also, as a good practice it is suggested that we should always declare the variables at the start of the function definition.