Javascript notes - Part 2 - Variable declaration

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 }

0_mYuuRwjUfUOAdHpo.jpeg

See more here -