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.