Programming Language
JavaScript
Variables
Var Let Const

Understanding var, let, and const in JavaScript

In JavaScript, we have three ways to declare variables: var, let, and const. The introduction of let and const in ES6 gave us more control over variable scope and reassignment. Let's break down why let and const were introduced and how they differ from var.

var in JavaScript

Before ES6, var was the only way to declare variables. Variables declared with var are function-scoped, meaning they can be accessed within the entire function they are declared in, even if declared inside a block.

Variables declared with var are function-scoped. This means they can be accessed outside the block they are declared in, even if that block is within a function or loop.

var Examples:

console.log(y); // Output: undefined
var y = 5;
console.log(y); // Output: 5
 
// For loop is block-scoped
for (var i = 0; i < 10; i++) {
  var message = "I'm accessible outside the loop";
}
 
console.log(message);
// Output: I'm accessible outside the loop
 
// Block scope
if (true) {
  var inside = "I'm inside Block";
}
console.log(inside);
// Output: I'm inside Block
 
/** The var variables are accessible outside the loop and block they were declared in. */
 
 
// Function Scope
function example() {
  var x = 1;
  if (true) {
    var x = 2; // Same variable!
    console.log(x); // Output: 2
  }
  console.log(x); // Output: 2
}
example();
/** The variable x is accessible throughout the function, even though it is redeclared inside the if block. This can lead to unexpected behavior. */
 
// Function scope
function showMessage() {
  var functionScoped = "Only inside this function";
  console.log(functionScoped);
}
showMessage();
// Output: Only inside this function
console.log(functionScoped);
// Output: ReferenceError: functionScoped is not defined
 
/**
 * The variable 'functionScoped' is only available inside the 'showMessage' function.
 * You cannot use it outside the function, which is why you get an error.
 */
 
// Declare a global variable 'num' and assign it the value 10
var num = 10;
 
// Define a function named 'getNumber'
function getNumber() {
  // Attempt to log the value of 'num' inside the function
  console.log(num); // This will log 'undefined' due to hoisting
 
  // Declare a local variable 'num' and assign it the value 22
  var num = 22; // This declaration is hoisted to the top of the function scope
}
 
// Call the function 'getNumber'
getNumber();

Hoisting Example:

// Example of hoisting with function declarations
console.log(greet());
// Output: Hello, World! (function declarations are hoisted)
 
function greet() {
  return "Hello, World!";
}
 
// Example of hoisting with variables
console.log(message);
// Output: undefined (due to hoisting)
var message = "This is a hoisting example.";
console.log(message);
// Output: This is a hoisting example.
 
// Function to illustrate hoisting with variables
function checkNumber(num) {
  if (num > 10) {
    var result = "Greater than 10"; // This variable is hoisted
    return result;
  } else {
    return result;
    // result is undefined here due to hoisting
  }
}
 
console.log(checkNumber(15));
// Output: Greater than 10
console.log(checkNumber(5));
// Output: undefined

Example: Global Scope

var globalVar = "I'm a global variable";
 
function displayGlobalVar() {
  console.log(globalVar); // Output: I'm a global variable
}
 
displayGlobalVar();
console.log(globalVar); // Output: I'm a global variable

Example: Function Scope

function localScope() {
  var localVar = "I'm a local variable";
  console.log(localVar); // Output: I'm a local variable
}
 
localScope();
console.log(localVar); // Output: ReferenceError: localVar is not defined

Example: Hoisting

console.log(hoistedVar); // Output: undefined
var hoistedVar = "I am hoisted";
console.log(hoistedVar); // Output: I am hoisted

let in JavaScript

Variables declared with let are block-scoped, meaning they are only accessible within the block they are declared in.

Example: Block Scope

let outside = "Outside";
 
if (true) {
  let inside = "Inside";
  console.log(inside); // Output: Inside
}
 
console.log(outside); // Output: Outside
console.log(inside); // Output: ReferenceError: inside is not defined

No Redeclarations

let x = 10;
// let x = 20; // SyntaxError: Identifier 'x' has already been declared
 
x = 20; // This is allowed
console.log(x); // Output: 20

const in JavaScript

Variables declared with const are block-scoped and cannot be reassigned. However, if the variable is an object, the properties of the object can be modified.

Example: Constant Declaration

const constantVar = "I can't be changed";
// constantVar = "New value"; // TypeError: Assignment to constant variable
 
console.log(constantVar); // Output: I can't be changed

Modifying Object Properties

const person = {
  name: 'Alice',
  age: 25
};
 
person.age = 26; // Allowed
console.log(person.age); // Output: 26
 
// person = { name: 'Bob', age: 30 }; // TypeError: Assignment to constant variable

Scope in JavaScript

Global Scope

  • Variables declared outside any function or block have a global scope. They can be accessed from anywhere in the code.

Function Scope

  • Variables declared inside a function are only accessible within that function.

Block Scope

  • Variables declared with let and const inside a block are only accessible within that block.

Lexical Scope

  • JavaScript uses lexical scoping, which means that the scope of a variable is determined by its position in the source code. Nested functions have access to variables declared in their outer scope.

Example: Lexical Scope

function outerFunction() {
  let outerVar = "I am outside!";
 
  function innerFunction() {
    console.log(outerVar); // Output: I am outside!
  }
 
  innerFunction();
}
 
outerFunction();
 

Closures

A closure is a function that has access to its own scope, the scope of the outer function, and the global scope.

Example: Closures

function outerFunction() {
  let outerVar = "I am outside!";
 
  function innerFunction() {
    console.log(outerVar);
  }
 
  return innerFunction;
}
 
const closureFunction = outerFunction();
closureFunction(); // Output: I am outside!

In the above example, innerFunction forms a closure. It retains access to outerVar even after outerFunction has finished execution.

When to Use var, let, and const

var

  • Use var for variables that need to be function-scoped.
  • Rarely used in modern JavaScript due to the introduction of let and const.

let

  • Use let for variables that need to be block-scoped.
  • Ideal for variables that will change value within a block.

const

  • Use const for variables that should not be reassigned.
  • Ideal for constants and variables that will not change.

Summary

  • var is function-scoped and can be redeclared and updated. It is hoisted to the top of its scope.
  • let is block-scoped and can be updated but not redeclared within the same scope.
  • const is block-scoped and cannot be updated or redeclared, but object properties can be modified.
  • Global scope variables are accessible from anywhere in the code.
  • Function scope variables are accessible only within the function they are declared in.
  • Block scope variables are accessible only within the block they are declared in.
  • Lexical scope means nested functions have access to variables declared in their outer scope.
  • Closures allow functions to retain access to their lexical scope even after the outer function has completed.

Understanding the differences between var, let, and const helps you write cleaner, more predictable code. As a general rule, prefer const by default, use let when you need to reassign, and avoid var unless you have a specific reason to use it.