Javascript notes - Part 2 - Variable declaration
The difference between var, let, and const
ES2015 introduced two new keywords for declaring variables - var
and const
. Thus including the original var
. Thus, now we have three keywords for declaring variables in Javascript.
Before we understand the difference between var
, let
, and const
, we need to understand the following three things:
- Variable declaration vs Initialization
- Scope (specifically function scope)
- Hoisting
Variable declaration vs Initialization
A variable declaration introduces a new identifier. In Javascript, variables are initialized with the value of undefined
when they are created.
var name
console.log(name)
Initialization is when you first assign a value to a variable.
// name identifier is assigned with string value Shanu
name = "Shanu"
Scope
Scope defines where a variable and functions are accessible inside of your program. In Javascript, there are two types of scopes -
- Global scope
- Function scope
According to ECMAScript spec -
If variable statement occurs inside a function declaration, the variables are defined with function-local scope in that function. Otherwise, they are defined with global scope, that is, they are defined with global scope, that is they are created as members of the global object.
function getDate() {
var date = new Date()
return date
}
console.log(date) // reference error
The locally scoped variable can be accessed by a nested function.
function getDate() {
var date = new Date()
function formatDate() {
return date.toDateString().slice()
}
return formatDate()
}
var
has function scope not block scope.
function discountPrices(prices, discount) {
var discounted = [];
for(var i=0; i<prices.length; i++) {
var discountedPrice = prices[i] * (1-discount);
var finalPrice = Math.round(discountedPrice * 100) / 100;
discounted.push(finalPrice)
}
console.log(i); // prints last value of i
console.log(discountedPrice); // prints last value of discountedPrice
console.log(finalPrice); // prints last value of finalPrice
return discounted;
}
console.log(discountPrices([100, 50, 20], 0.5)); // [50, 25, 10]
As we can see above, it is not block scope with var
variables but function scope. This was changed with the introduction of block-scoped declaration types - let
and const
.
Hoisting
When the Javascript interpreter evaluates code, it will move all function and variable declarations to the top of the current scope, this is referred to as Hoisting.
Code -
console.log(my_var); // undefined
var my_var;
Interpreted as -
var my_var;
console.log(my_var); // undefined
without the declaration present at all we will get a reference error.
Because of hoisting and var
being function scoped the discounted code is actually interpreted as below. (compare and see the difference)
function discountPrices(prices, discount) {
var discounted;
var i;
var discountedPrice;
var finalPrice;
discounted = [];
for(i=0; i<prices.length; i++) {
discountedPrice = prices[i] * (1-discount);
finalPrice = Math.round(discountedPrice * 100) / 100;
discounted.push(finalPrice)
}
console.log(i); // prints last value of i
console.log(discountedPrice); // prints last value of discountedPrice
console.log(finalPrice); // prints last value of finalPrice
return discounted;
}
console.log(discountPrices([100, 50, 20], 0.5)); // [50, 25, 10]
If you do not declare the variable with var
, let
or const
keyword. The interpreter will try to find a declaration and keep going up a level in scope due to hoisting and create it as a property in the global object if it doesn't find the declaration, see example below:
function test(){
for(var x=0; x<1; x++){
y = 10;
}
}
console.log(y); //10
The above is the same as the below code to the interpreter.
var y;
function test(){
for(var x=0; x<1; x++){
y = 10;
}
}
console.log(y); //10
var
vs let
vs const
var
- Function scoped.
- Previously
var
variable can be redeclared. - Hoisted with default initialization.
var x = 2;
console.log(x); // 2
var x = 3;
console.log(x); // 3
let
- Block scoped.
- Re-declaration is not allowed.
- Hoisted without default initialization.
let x = 2;
console.log(x); // 2
let x = 3; // SyntaxError: Identifier 'x' has already been declared.
const
- same as
let
but to be initialized at the time of declaration. - Assignment not allowed
- not deeply immutable, items inside a complex object are still mutable.
- for example, items of an array, objects, etc.
const x; // SyntaxError: Missing initializer in const declaration
const x = 2;
x = 3; // TypeError: Assignment to constant variable.
const x = {};
x = "test"; // TypeError: Assignment to constant variable.
const x = {};
console.log(x); // {}
x.a = 1;
console.log(x); // { a: 1 }
See more here -