Labs ICT
Pro Login

Variables

6 min read | JavaScript Tutorial

Want the full learning experience?

Get structured courses, certificates, projects, and instructor support with LabsICT Pro.

Explore Pro Courses

What Are Variables?

Variables are containers for data. Think of them as labeled jars — you put a value in, give it a name, and refer to it later. Every time you store a username, a score, or a list of items, you are using a variable.

JavaScript gives you three ways to declare variables: var, let, and const. They all store values, but they behave differently. Understanding those differences will save you from bugs that are hard to track down.

Declaring with let

let is the modern way to declare a variable that will change later. Use it when you know the value will be reassigned.

let score = 0;
score = 10; // reassign — this is fine

let name = "Alice";
name = "Bob"; // also fine

You can also declare let without assigning a value. It will hold undefined until you assign something.

let age;
console.log(age); // undefined
age = 25;

Declaring with const

const works like let, but you cannot reassign it. Once you set a value, that name is locked to that value. Use const by default — it tells anyone reading your code that this value is not supposed to change.

const pi = 3.14159;
// pi = 3; // TypeError: Assignment to constant variable

const username = "Alice";
console.log(username); // Alice

Here is the part that confuses a lot of beginners. const prevents reassignment, but it does not freeze the value. If you store an object or an array in a const, you can still change its contents.

const user = { name: "Alice" };
user.name = "Bob"; // this works — mutating the object
console.log(user.name); // Bob

// user = {}; // TypeError: Assignment to constant variable

const list = [1, 2, 3];
list.push(4); // this works — mutating the array
console.log(list); // [1, 2, 3, 4]

Think of const as locking the jar label, not the contents. You cannot reassign the name, but you can change what is inside.

Declaring with var (The Old Way)

var was the only way to declare variables before 2015. It still works, and you will see it in older code, but it has quirks that cause real bugs. The biggest problem is that var ignores block scope.

var x = 10;
if (true) {
  var x = 20; // same variable — overwrites the outer one
  console.log(x); // 20
}
console.log(x); // 20 — not 10 like you might expect

In modern code, always use let or const. Reserve var for understanding legacy code.

let, const, and var Compared

Feature const let var
Scope Block Block Function
Reassign? No Yes Yes
Redeclare in same scope? No No Yes
Hoisting TDZ (error if accessed before declaration) TDZ (error if accessed before declaration) Hoisted, initialized to undefined

Block Scope vs Function Scope

Scope decides where a variable is visible. let and const are block-scoped — they only exist inside the { } where they are declared. var is function-scoped — it leaks out of blocks.

// let respects block scope
if (true) {
  let inside = "only here";
  console.log(inside); // only here
}
// console.log(inside); // ReferenceError: inside is not defined

// var ignores block scope
if (true) {
  var leaked = "I escape the block";
}
console.log(leaked); // I escape the block

This is why let is the right choice for loop counters. Each iteration gets its own binding.

for (let i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 100);
}
// Output: 0, 1, 2

for (var j = 0; j < 3; j++) {
  setTimeout(() => console.log(j), 100);
}
// Output: 3, 3, 3 — var leaked out of the loop

Hoisting and the Temporal Dead Zone

JavaScript processes declarations before running your code. This is called hoisting. But the three keywords handle it differently.

A var declaration is hoisted and initialized to undefined. You can read it before the declaration line — you just get undefined.

console.log(greeting); // undefined — no error
var greeting = "hello";
console.log(greeting); // hello

let and const are also hoisted, but they are not initialized. From the start of the block until the declaration, the variable sits in the Temporal Dead Zone (TDZ). Accessing it throws a ReferenceError.

try {
  console.log(name); // ReferenceError (TDZ)
  let name = "Alice";
} catch (e) {
  console.log(e.name); // ReferenceError
}

The TDZ is a feature. It catches accidental use-before-declaration that var silently hides.

Variable Naming Rules

JavaScript enforces a few hard rules for variable names:

  • Names may contain letters, digits, underscores (_), and dollar signs ($)
  • Must begin with a letter, underscore, or dollar sign — not a digit
  • Case-sensitive: age and Age are different variables
  • Reserved keywords like if, for, class, return cannot be used as names

On top of the rules, follow these conventions for readable code:

  • Use descriptive names: userName, not x
  • Use camelCase for variables and functions: firstName, itemCount
  • Use UPPER_SNAKE_CASE for fixed constants: const MAX_SIZE = 100
  • Avoid single letters except for short-lived loop counters (i, j)
let firstName = "Ada"; // good — descriptive camelCase
const TAX_RATE = 0.2; // good — constant in UPPER_SNAKE_CASE
let $element = "ok"; // legal — $ is allowed
let _private = "ok"; // legal — _ is allowed
// let 1st = "x"; // SyntaxError: cannot start with a digit

JavaScript Is Dynamically Typed

A variable does not have a fixed type. The same variable can hold a string now and a number later.

let thing = "hello";
thing = 42; // perfectly legal
thing = true; // also fine
thing = [1, 2, 3]; // and this

This is different from languages like Java or C++, where you declare the type upfront. JavaScript figures out the type at runtime. It gives you flexibility, but it also means you need to be careful — mixing types accidentally can cause weird bugs.

Common Mistakes

  • Using var in modern code — It causes scope-related bugs. Use let or const instead.
  • Redeclaring with letlet x = 1; let x = 2; throws a SyntaxError. You cannot redeclare in the same scope.
  • Assuming const makes objects immutableconst prevents reassignment, not mutation. Use Object.freeze() for true immutability.
  • Using a variable before declaring it — With let and const, this throws a ReferenceError due to the TDZ.

Which One Should You Use?

Use const by default. Switch to let only when you know the value needs to be reassigned. Avoid var in new code.

const apiUrl = "https://api.example.com"; // won't change
let counter = 0; // will be incremented
counter += 1;

const user = { name: "Alice" }; // object reference won't change
user.age = 25; // but contents can

This simple rule makes your code predictable and easier to debug.