Declaring and Using Variables in JavaScript – var, let, const, and Scope

In JavaScript, variables are containers for values and must be declared before use. This article explores the three main declaration forms — var, let, and const — and their differences in scope, mutability, and appropriate use cases. It also covers variable declarations in functions and catch blocks, helping developers write clearer and more maintainable code.

JavaScriptvariablesletconst

~3 min read · Updated Oct 14, 2025

Introduction


In JavaScript programs, values can appear as literals or be stored in variables. Think of variables as containers for values. To use a variable, it must first be declared. JavaScript offers several ways to declare variables, each with its own behavior and scope rules.


Declaring with var


The var keyword declares a variable in the function or global scope:


var name = "Kyle";
var age;

Variables declared with var are accessible throughout the function or file, even outside of blocks like if.


Declaring with let


let is similar to var but introduces block scope, meaning the variable is only accessible within the block it’s declared in:


var adult = true;
if (adult) {
  var name = "Kyle";
  let age = 39;
  console.log("Shhh, this is a secret!");
}
console.log(name); // Kyle
console.log(age);  // Error!

age is block-scoped to the if block, while name is not.


Block Scope and Its Benefits


Using let helps limit the visibility of variables, reducing the risk of name collisions. var is still useful when broader access is needed. Choosing between them depends on the context.


Declaring with const


const is like let but with an added restriction: it must be initialized at declaration and cannot be reassigned:


const myBirthday = true;
let age = 39;
if (myBirthday) {
  age = age + 1;       // OK
  myBirthday = false;  // Error!
}

const prevents reassignment but not mutation. Using const with objects can be misleading:


const actors = ["Morgan Freeman", "Jennifer Aniston"];
actors[2] = "Tom Cruise"; // Allowed :(
actors = [];              // Error!

The best use of const is for simple primitive values with meaningful names, like myBirthday instead of true.


Tip: Use const Safely


If you use const only for primitive values, you avoid confusion between reassignment (disallowed) and mutation (allowed). This is the safest way to use const.


Declaring Variables in Functions


Functions also declare variables. Parameters behave like internal variables:


function hello(name) {
  console.log(`Hello, ${name}.`);
}
hello("Kyle"); // Hello, Kyle

hello is declared in the outer scope, while name is scoped to the function body.


Declaring Variables in catch Blocks


Variables can also be declared in catch clauses. These are block-scoped, similar to let:


try {
  someError();
}
catch (err) {
  console.log(err);
}

err exists only within the catch block.


Conclusion


JavaScript variables can be declared using var, let, or const, each with distinct scope and mutability rules. Understanding these differences helps you write cleaner, more reliable code. Variables can also be declared in functions and catch blocks, making scope awareness essential for maintainable programming.


Written & researched by Dr. Shahin Siami

Related Articles

Coercive Conditional Comparison and Prototypal Classes in JavaScript – Understanding Implicit Logic and Legacy Inheritance Patterns

This article explores two advanced topics from Appendix A of You Don’t Know JS Yet: how JavaScript performs coercive comparisons in conditional expressions, and how prototypal class patterns were used before ES6 introduced the class keyword. Through practical examples, it clarifies how implicit boolean logic works and how prototype chains enable behavior delegation.

Continue

Value vs Reference and the Many Forms of Function Definitions

Value vs Reference and the Many Forms of Function Definitions

Continue

Prototypes in JavaScript – Delegation, Prototype Chains, and Dynamic this Behavior

Prototypes in JavaScript provide a mechanism for property delegation between objects. This article explains how prototype chains work, how to create linked objects using Object.create, and how property access and assignment behave in relation to delegation. It also explores how the dynamic nature of this enables prototype-based method reuse across multiple objects.

Continue

Closure and this in JavaScript – Scope Memory and Dynamic Execution Context

Closure and this are two foundational and often misunderstood concepts in JavaScript. This article defines closure as a function’s ability to remember variables from its outer scope, and explains how this refers to the dynamic execution context of a function call. Through practical examples, it clarifies the difference between static scope and dynamic context.

Continue

Iteration in JavaScript – The Iterator Pattern, Built-in Iterables, and Standard Data Consumption

Iteration is a foundational pattern for processing data in JavaScript. This article explores the iterator protocol, how to consume iterators using for..of loops and the spread operator, the distinction between iterators and iterables, and how built-in structures like arrays, strings, maps, and sets support standardized iteration. It also shows how to customize iteration for your own data structures.

Continue

Modules in JavaScript – From Classic Patterns to ES Modules and Structural Differences

Modules in JavaScript, like classes, are designed to group data and behavior into logical units. This article explores the classic module pattern using factory functions, compares it to class-based design, and introduces ES Modules (ESM) introduced in ES6. It explains how modules are defined, exported, imported, and instantiated, and highlights the differences in structure and usage.

Continue