Welcome to your first lesson! We're kicking off your journey to becoming a web developer by building a strong foundation in modern JavaScript.
In this lesson, you'll learn how to declare variables, which are the fundamental containers for data in any program. We'll focus on the modern keywords, let and const, and the crucial concept of "block scope." Mastering this is the first step toward writing the clean, predictable, and maintainable code that professional developers strive for. While you might see the older var keyword in legacy code, our focus will be on the current standards used in the industry today.
What is Scope?
Before we dive into the keywords, let's talk about scope. In programming, scope defines where a variable is accessible or "visible." Think of it as a set of rules determining which parts of your code can see and use which variables. Your experience with Python's global and function scopes will be a helpful starting point here. JavaScript has similar ideas, but with some important distinctions.

The Old Way: var and Its Problems
Historically, JavaScript only had one way to declare variables: the var keyword. The biggest issue with var is that it has function scope. This means a variable declared with var is accessible anywhere inside the function it's defined in, even outside of the specific code block (like an if statement or a for loop) where you declared it.
This can lead to confusing bugs. For example, a variable from a loop "leaking" out and being accessible after the loop has finished.
To see a practical demonstration of the problems with var, particularly how it behaves in loops and how it can interfere with the global window object in a browser, watch the following video from Programming with Mosh.
JavaScript Let vs Var vs Constant | Mosh
This video clearly illustrates two major problems with var: its function-scoped nature and its tendency to pollute the global scope.
Watch the segments from the beginning until 05:54. Focus on the for loop example to see how var leads to unexpected behavior, and understand why attaching variables to the global window object is problematic.
As you can see, the behavior of var is often not what you'd intuitively expect, which is why the JavaScript language introduced two new, more predictable keywords.
The Modern Way: let, const, and Block Scope
To solve the problems of var, modern JavaScript (ES6 and later) introduced let and const. Their most important feature is that they are block-scoped.
A block is any section of code enclosed in curly braces {...}. This includes if/else statements, for and while loops, or even just a standalone pair of braces. When you declare a variable with let or const inside a block, it only exists and is only accessible inside that block.
This prevents variables from "leaking" out and makes your code much easier to reason about.
let isRaining = true;
if (isRaining) {
let weatherMessage = "Bring an umbrella!";
console.log(weatherMessage); // "Bring an umbrella!"
}
// console.log(weatherMessage); // This would cause an error!
// weatherMessage is not defined in this scope.
This predictable, block-level scoping is a key feature of modern JavaScript development.
Test your understanding!
What will be logged to the console when this code runs?
let userRole = "admin";
let accessLevel = 1;
if (userRole === "admin") {
let accessLevel = 3;
console.log("Inside block:", accessLevel); // First log
if (true) {
const canDelete = true;
console.log("Inside nested block:", accessLevel); // Second log
}
}
console.log("Outside block:", accessLevel); // Third log
Show answer
The console will show:
Inside block: 3Inside nested block: 3Outside block: 1
Explanation:
- The first and second
console.logstatements are inside theifblock where a newaccessLevelvariable was declared withlet accessLevel = 3. This "shadows" the outer variable, so3is printed. - The third
console.logis outside that block, so it can only see the originalaccessLevelvariable that was declared at the top level with the value1.
let vs. const: Reassignment
So, if both let and const are block-scoped, what's the difference between them? It comes down to reassignment.
let: Declares a variable whose value can be changed (reassigned).const: Declares a "constant" whose value cannot be reassigned once set.
let score = 10;
score = 15; // This is fine.
const name = "Alex";
// name = "Bob"; // This would throw a TypeError: Assignment to constant variable.
A crucial point of clarification: when you declare an object or an array with const, you can still modify the contents of that object or array. You just can't reassign the variable to a completely new object or array.
const user = {
name: "Sam",
id: 123
};
user.name = "Samantha"; // This is allowed!
// user = { name: "Jane", id: 456 }; // This would throw an error.
Best Practice for let and const
The modern convention, and a key principle of writing robust code, is to always use const by default. Only switch to let if you know you will need to reassign the variable later, such as a counter in a loop. This helps prevent accidental changes to your variables.
The following video provides an excellent, concise overview of all these concepts, comparing var, let, and const directly.
Differences Between Var, Let, and Const
This video from Web Dev Simplified clearly demonstrates the scope, reassignment, and hoisting differences between all three keywords.
Watch the sections from 00:44 to 03:00 and from 05:26 to 08:37. Pay close attention to the if block example for scope, and the explanation of how const works with objects.
A Final Piece of the Puzzle: Hoisting
One last "gotcha" of var is a behavior called hoisting. JavaScript conceptually moves var declarations (but not their initial values) to the top of their scope. This means you can use a variable before it's declared, and instead of an error, you get undefined. This can hide bugs and make code unpredictable.
let and const also have a form of this, but they behave differently. If you try to access them before their declaration, JavaScript will throw a ReferenceError. This is much safer, as it immediately tells you that you're trying to use a variable before it's been defined.
For a more detailed textual explanation of scope and hoisting, the following article is a great resource.
Understanding Variables, Scope, and Hoisting in JavaScript
The article 'Understanding Variables, Scope, and Hoisting in JavaScript' from DigitalOcean provides a thorough written guide to these concepts. The table is an especially useful summary.
Read the sections 'Difference Between var, let, and const', 'Variable Scope', and 'Hoisting'. The comparison table in the first section is a fantastic reference that summarizes the key differences.
Key Takeaways
You've just learned the modern foundation of variable declaration in JavaScript. Here's a quick summary of the rules to follow:
- Stop using
var. Its function scope and hoisting behavior are sources of bugs. - Use
letandconst. They are block-scoped, which is more predictable and aligned with other programming languages. - Default to
const. This prevents accidental reassignment and makes your code's intent clearer. - Use
letonly when you know you need to reassign a variable's value.
Conclusion
Congratulations on completing your first lesson! You now understand how to use let and const to declare variables and the critical importance of block scope. This practice is fundamental to writing modern, professional JavaScript.
In the next lesson, we will explore another cornerstone of modern JS: arrow functions. You'll see how they provide a more concise syntax for writing functions and how they solve a common problem with scope that you'll encounter frequently when writing interactive web applications.