When writing our code, we calculate values and, most times, we need to store them in memory locations for future use. That is why we need variables. In Javascript, we can declare variables in various ways, each type of declaration gives the variable unique characteristics. This article will explore javascript variable types, and how they behave under the following situations:
- Initialization
- Availability before declaration
- Scope
- Redeclaration
- Update
Initializing javascript variable types
When we need Javascript to create a variable for us, we carry out a variable declaration using either the var
, let
or const
variable declarations. Once Javascript creates the variable, it initializes the variable with the value we give on the right-hand side of the assignment which makes up the declaration. In the case of variables declared using var
or let
, initialization is optional. However, an initial value is required for const
variables. Without an initial value, Javascript will report a SyntaxError
.
var a = 10; // initial value is 10
let b = 12; // initial value is 12
const c = 14; // initial value is 14
var d; // initial value is undefined
let e; // initial value is undefined
const f; // syntax error, initial value required
Availability before declaration
What happens if we try to access a variable before we declare it in code? let
and const
variables require that they be declared first before any attempt to access them. The next example shows what will happen when we try to access a let
variable before it has been declared.
// Try to display the contents of variable 'num'
console.log(num)
// Now declare 'num' with let
let num;
Output:
ReferenceError: Cannot access 'num' before initialization
Any attempt to access the variable resulted in an error. The same can be said for const
variables. The story is however very different for variables declared with var
. Notice what happens in the next example.
console.log(num);
var num = 34;
console.log(num);
Output:
undefined
34
From the output, we do not see any error message. Instead, the first console.log()
prints undefined
, as if num
were already declared. Then after num
is declared, the next console.log()
displays 34
. In effect, Javascript creates an uninitialized var
declaration before the first access of num
, and moves it to the top of the containing scope. This Javascript behaviour is called hoisting. The code behaves like the example code below.
var num;
console.log(num);
var num = 34;
console.log(num);
Scope
Scope determines how accessible a variable is. In Javascript, we could have:
- Global scope, which means the whole application has access to the variable.
- Function scope, where all code can access the variable
- Block scope, where only code within the block (including nested blocks) can access the variable
Variables declared with var
have function scope because they are accessible throughout the function in which the declaration appears. However, such variables are not accessible outside the function, and any attempt to access them causes a ReferenceError to occur during runtime. See the next example.
function test () {
var msg = "This is a message from test function";
// display the contents of 'msg'
console.log("msg = ", msg);
}
// call the 'test' function
test();
console.log("msg = ", msg); // Error here!!!
Output:
msg = This is a message from test function
ReferenceError: msg is not defined
The above code example raised a ReferenceError
because the msg
was out of scope. To eliminate this error, we could declare msg
before accessing outside test()
.
function test () {
var msg = "This is a message from test function";
// display the contents of 'msg'
console.log("msg = ", msg);
}
// call the 'test' function
test();
// declare 'another' 'msg' variable
var msg = "This message is outside the test function scope";
console.log("msg = ", msg); // Ok!!!
Output:
msg = This is a message from test function
msg = This message is outside the test function scope
This time, we do not have an error, as the second console.log()
could now find msg
outside the function scope.
In summary, var
variables are not accessible outside the function they are declared in.
Both let
and const
variables have block scope. Code outside the scope of where we declared the variables cannot access them. However, code inside the scope and nested scopes can access let
and const
variables we declare within a scope. The next example demonstrates this.
{
// declare the variable here
var greet = "Hello";
let name = "Fred";
const pi = 3.141;
{
// accessing through nested scope
console.log("nested block scope greet = ", greet);
console.log("nested block scope name = ", name);
console.log("nested block scope pi = ", pi);
}
// access in the defined scope
console.log("main block scope greet = ", greet);
console.log("main block scope name = ", name);
console.log("main block scope pi = ", pi);
}
// access out of the defined scope
console.log("out of block scope greet = ", greet);
console.log("out of block scope name = ", name);
console.log("out of block scope pi = ", pi);
Output:
nested block scope greet = Hello
nested block scope name = Fred
nested block scope pi = 3.141
main block scope greet = Hello
main block scope name = Fred
main block scope pi = 3.141
out of block scope greet = Hello
ReferenceError: name is not defined
The example defines three variables in the main scope; greet
, name
, and pi
. greet
is declared with the var
keyword, name
is declared with the let
keyword, and pi
is declared with the const
keyword.
The console.log()
attempts to access the variables from the main block scope, and the nested block scope succeeded. However, when an attempt was made to access the variables outside the scope under which they were declared, only the var
variable could be accessed. The let
variable name could not be accessed since it is now dead, or out of scope. A similar remark could be made about the const
variable pi
, and we see it in action if we comment out the line trying to access name
{
// declare the variable here
var greet = "Hello";
let name = "Fred";
const pi = 3.141;
{
// accessing through nested scope
console.log("nested block scope greet = ", greet);
console.log("nested block scope name = ", name);
console.log("nested block scope pi = ", pi);
}
// access in the defined scope
console.log("main block scope greet = ", greet);
console.log("main block scope name = ", name);
console.log("main block scope pi = ", pi);
}
// access out of the defined scope
console.log("out of block scope greet = ", greet);
// console.log("out of block scope name = ", name);
console.log("out of block scope pi = ", pi);
Output:
nested block scope greet = Hello
nested block scope name = Fred
nested block scope pi = 3.141
main block scope greet = Hello
main block scope name = Fred
main block scope pi = 3.141
out of block scope greet = Hello
ReferenceError: pi is not defined
We still get a ReferenceError
. We cannot access either let
or const
variables out of the scope they were defined.
In summary, let
and const
variables are block-scoped: their lifespan is the scope within which they were defined. Any attempt to access them outside the scope they were defined results in a ReferenceError
since at that point, the variable is no more defined.
Redeclaring javascript variable types
The next example shows attempts to redeclare the variables greet
, name
, and pi
within the same scope and a nested scope.
{
// initial declaration
var greet = "Hello";
let name = "Fred";
const pi = 3.14;
{
// redeclaration in nested scope, no problems here
var greet = "How are you?";
let name = "Agatha";
const pi = 3.141;
}
// redeclaration in main block scope, let and const will raise error
var greet = "Hi there";
let name = "Maggie";
const pi = 3.14152;
}
Javascript will view the lines let name = "Maggie";
and const pi = 3.14152;
as syntax errors since they have already been declared. However, redeclaring var does not raise a syntax or runtime error. So, redeclaration is only allowed for let
and const
variables when they are done within different scopes. Redeclaration does not affect the value contained in a var
variable unless we assign a new value. Check out the next example for a demo of this.
var fruit = "cherry";
console.log("First declaration of fruit contains: ", fruit);
var fruit;
console.log("Second declaration of fruit without initialization contains: ", fruit);
var fruit = "apple";
console.log("Third declaration of fruit with initialization contains: ", fruit);
Output:
First declaration of fruit contains: cherry
Second declaration of fruit without initialization contains: cherry
Third declaration of fruit with initialization contains: apple
Updating javascript variable types
Once we declare const
variables, they cannot be updated. We can see this in the following example code.
var age = 12; // declare 'age' with var
age = 23; // update: no problem
let city = "Mumbai"; // declare 'city' with let
y = "Hyderabad"; // update: no problem
const e = 2.81; // declare 'e' with const
e = 2.818; // update: error!!!
Output:
TypeError: Assignment to constant variable.
The line e = 2.818;
that attempts to update the variable e
raises a TypeError
at runtime. var
and let
, on the other hand, do not have any problems with updates.
Conclusion
We have considered the three types of variables that can be declared in Javascript; var
, let
and const
. We considered the behaviour of each with respect to:
- Initialization:
const
variables must be initialized before use. When not specified for let and var, the initial value isundefined
. - Availability before declaration:
let
andconst
must be declared before accessing them.var
variables are hoisted when Javascript encounters an access attempt before the variable declaration. Scope
:let
andconst
variables are block-scoped and available within the scope they are defined, including nested scopes. Variables declared withvar
are available throughout the function in which their declaration is found, no matter which inner scope the declaration is found.- Redeclaration:
let
andconst
variables can only be redeclared in nested block scopes.var
variables, however, do not have this limitation, as they can be redeclared even within the same scope. - Update: Once declared and initialized,
const
variables cannot be updated.let
andvar
variables can be updated after declaration.
Thanks for reading the tutorial to the end. We hope you have been able to differentiate between the three kinds of variable declarations in Javascript. You can continue your learning by exploring more of our Javascript articles.