Understand JavaScript Variables In Depth
Variables are named memory locations. When we declare a variable in JavaScript, it means that a memory location is allocated to store some value and that location can be accessed using the variable name.
Here is an example of a variable declaration.
var name;
Here name
is pointing towards some memory location in RAM. One of the ways to store some value to that memory location is by using the assignment operator(=
).
name = "Backbencher";
Variable Declaration
In JavaScript, a variable can be declared using any one of the following keywords.
var
let
const
var
var
can declare either global scoped or function scoped variables.
var a;function baz() {
var b;
}
Variable a
is declared outside of all functions. Hence, a
is in global scope. Variable b
is declared inside a function baz()
. Hence, b
is in function scope, ie the scope of baz()
. The variable b
can be used only inside the function baz()
.
Default value
Default value of a variable declared using var
is undefined
.
var a;
console.log(a); // undefined
Variable redeclaration
A variable declared using var
can be redeclared. It does not throw any error even in strict mode.
var a = 3;
var a = 5;
console.log(a); // 5
JavaScript engine is keeping a track of all variables declared. So in line 2, instead of redeclaring a
, the engine maps to the memory location created in line 1. In that case, what is the output of the below code?
var a = 3;
var a;
console.log(a);
If you expected undefined
, it is wrong. The output is 3
. Here also in line 2, it is a redeclaration of variable a
. JavaScript engine skips that. Since there is no assignment in line 2, previous value(3
) is retained.
Hoisting
Variables declared using var
are created before executing any code. Before interpreting JavaScript code line by line, JavaScript engine parses through the full code. During this parsing step, the engine allocates memory to variables declared using var
and assign undefined
. This behaviour is called hoisting of variables.
console.log(a); // undefined
var a;
Here, line 1 is trying to print the value of a
. But the variable a
is declared only in line 2. Due to hoisting, when JavaScript engine executes line 1, variable a
is already created. That is why above code outputs undefined
.
Since the memory is allocated during the parsing step, for a developer it seems like JavaScript is hoisting or moving the variable declaration to the top of the current scope, before execution. For example, the JavaScript code we write looks like below.
console.log(a);
var a;
console.log(b);
var b;
console.log(c);
var c;
After the parsing step, the code looks like below for the JavaScript engine.
var a;
var b;
var c;
console.log(a);
console.log(b);
console.log(c);
This can be the reason why this behaviour is called hoisting like in flag hoisting.
During the hoisting process, only the memory allocation is done. Assigning values to the memory location happens only during execution. In that context, what will be the output of the following code?
console.log(a); // undefined
var a = 6;
Above code prints undefined
as output. It is because the value 6
is assigned to the variable only when the JavaScript engine reaches line 2. Till that time the value of a
is undefined
.
Variable as global object property
When a variable is declared using var
in global scope, that variable is added as a non-configurable property to the global object.
var myVar = 4;
console.log(window.myVar); // 4
Here the myVar
property of window
cannot be deleted using delete
operator.
var myVar = 4;
delete window.myVar;
console.log(window.myVar); // 4
let
A variable declared using let
keyword is block scoped. A block is a section of code wrapped in curly braces({}
).
{
let a;
}
console.log(a); // ReferenceError: a is not defined
Global let variable
Just like declaring a global variable using var
, we can declare a global variable using let
. But, when declaring a global variable using let, it is not added to the global object as var
does.
let letVariable = "let it Backbencher";
var varVariable = "var it Backbencher";
console.log(window.letVariable); // undefined
console.log(window.varVariable); // "var it Backbencher"
let variable redeclaration
When a variable is redeclared using let
, it throws SyntaxError.
let a;
let a; // SyntaxError: Identifier 'a' has already been declared
Even when the first variable is declared using var
, the error appears.
var a;
let a; // SyntaxError: Identifier 'a' has already been declared
Temporal Dead Zone
A variable declared using let
cannot be accessed before its declaration. The variable is treated to be in Temporal Dead Zone. Consider the following code.
console.log(a);
console.log(b);
var a;
let b;
Before executing the code line by line, there is a parsing step. During parsing, all the declarations are understood and memory allocation and scope is defined. When memory is allocated for a
, a value of undefined
is automatically assigned to it. But for b
, memory is allocated but not assigned with a value.
After parsing, the execution starts line by line. So when the execution reaches line 2, there is a memory for b
, but is in a non-readable condition(Temporal Dead Zone). In line 4, the engine assigns undefined
to b
after seeing the declaration statement. Statements if any after line 4 can access the variable b
.
const
const
is used to declare variables whose values cannot be re-assigned. In effect, const
creates constant variables.
const a = 5;
a = 4; // TypeError: Assignment to constant variable
Declared and assigned
A constant variable need to be assigned at the same time of declaration. If we try to separate the declaration and assignment operation, it throws error.
const a; // SyntaxError: Missing initializer in const declaration
a = 5;
Block scoped
A variable declared using const
is block scoped.
{
const a = 5;
}
console.log(a); // ReferenceError: a is not defined
Variable redeclaration
A constant variable cannot be redeclared. The initial declaration can be either through var
, let
or const
.
var a;
const a = 5; // SyntaxError: Identifier 'a' has already been declared
Hoisting
A variable declared using const
is not hoisted, just like let
.
console.log(a); // ReferenceError: Cannot access 'a' before initialization
const a = 5;
Here note the error message in line 1: “Cannot access ‘a’ before initialization”. That means, the engine knows that the variable is going to be declared later. That awareness is obtained during the parsing step before code execution. In line 1, variable a
is said to be in Temporal Dead Zone.
Constant objects
Elements of a constant object can be updated. It is because, when we assign an object to a constant variable, only the reference of the object is saved in the variable. Even when we update the object elements, the reference does not change. When the reference is kept constant, there will not be any error.
const obj = {
name: "Backbencher"
};obj.name = "Updated";console.log(obj.name); // "Updated"