JS Variables Guide: How to Declare and Use Them

Learn how to declare, initialize, and use JavaScript variables with let, const, and var. This guide covers variable types, assignment, reassignment, and practical patterns every beginner needs to know.

JavaScriptbeginner
13 min read

Variables are the foundation of every JavaScript program. They are named containers that store values so you can reference, update, and manipulate data throughout your code. Without variables, every calculation would be lost the moment it was computed, and you would have no way to track user input, API responses, or application state.

Think of a variable like a labeled box in a warehouse. The label is the variable name (userName, totalPrice, isLoggedIn), and the contents are the value ("Alice", 49.99, true). You can look inside the box to read the value, swap the contents for a new value, or move the box around your program. JavaScript gives you three keywords for creating these boxes: let, const, and var.

This guide covers everything a beginner needs to know about JavaScript variables: how to declare them, what values they hold, when to use each keyword, and the common mistakes that trip up new developers.

Declaring Variables: The Three Keywords

JavaScript provides three ways to declare a variable. Each has different behavior for reassignment, scope, and hoisting.

javascriptjavascript
// Using let: can be reassigned, block-scoped
let currentScore = 0;
currentScore = 10; // Allowed: let variables can be reassigned
 
// Using const: cannot be reassigned, block-scoped
const MAX_RETRIES = 3;
// MAX_RETRIES = 5; // Error: Assignment to constant variable
 
// Using var: can be reassigned, function-scoped (legacy)
var playerName = "Alice";
playerName = "Bob"; // Allowed: var variables can be reassigned
KeywordReassignableScopeHoistedIntroduced
letYesBlock ({})Yes (but not initialized)ES6 (2015)
constNoBlock ({})Yes (but not initialized)ES6 (2015)
varYesFunctionYes (initialized as undefined)ES1 (1997)
Which Keyword Should You Default To?

Use const for every variable unless you know the value needs to change. If it does need to change, use let. Avoid var in modern JavaScript. This pattern makes your code easier to reason about because most values in a well-written program do not need reassignment.

Declaration vs. Initialization

There is an important distinction between declaring a variable (creating the name) and initializing it (assigning the first value).

javascriptjavascript
// Declaration only (no value assigned yet)
let temperature;
console.log(temperature); // undefined (declared but not initialized)
 
// Initialization (assigning the first value)
temperature = 22.5;
console.log(temperature); // 22.5
 
// Declaration + initialization in one step (recommended)
let humidity = 65;
console.log(humidity); // 65
 
// const MUST be initialized at declaration
const API_URL = "https://api.example.com";
// const API_KEY; // SyntaxError: Missing initializer in const declaration

Multiple Declarations on One Line

You can declare multiple variables in a single statement, but this can hurt readability:

javascriptjavascript
// Multiple declarations (technically valid but harder to read)
let x = 1, y = 2, z = 3;
 
// Preferred: one declaration per line for clarity
let width = 800;
let height = 600;
let depth = 100;

What Values Can Variables Hold?

JavaScript variables can hold any of the language's data types. These fall into two categories: primitive types and reference types.

Primitive Types

Primitives are simple, immutable values stored directly in the variable.

javascriptjavascript
// String: text data
const firstName = "Sarah";
const greeting = `Hello, ${firstName}!`; // Template literal
 
// Number: integers and decimals (no separate int/float types)
const age = 28;
const price = 49.99;
const negative = -15;
 
// Boolean: true or false
const isActive = true;
const hasPermission = false;
 
// Undefined: variable declared but not assigned
let middleName;
console.log(middleName); // undefined
 
// Null: intentionally empty value
const selectedItem = null;
 
// BigInt: very large integers (append n)
const largeNumber = 9007199254740991n;
 
// Symbol: unique identifier (advanced use)
const id = Symbol("user-id");

Reference Types

Reference types store a reference (memory address) to the actual data, which lives in a different area of memory called the heap.

javascriptjavascript
// Object: collection of key-value pairs
const user = {
  name: "Sarah",
  age: 28,
  role: "developer"
};
 
// Array: ordered list of values
const scores = [95, 87, 92, 78, 88];
 
// Function: reusable block of code
const calculateAverage = (numbers) => {
  const sum = numbers.reduce((total, n) => total + n, 0);
  return sum / numbers.length;
};
 
console.log(calculateAverage(scores)); // 88
Type CategoryTypesStored AsCopy Behavior
PrimitiveString, Number, Boolean, Undefined, Null, BigInt, SymbolValue itselfCreates independent copy
ReferenceObject, Array, Function, Date, RegExp, Map, SetMemory addressCopies the reference (both point to same data)
const Does Not Mean Immutable for Objects

Declaring an object or array with const prevents you from reassigning the variable to a completely new object, but you can still modify the properties or elements inside it. The reference is constant, not the contents.

javascriptjavascript
const config = { theme: "dark", fontSize: 16 };
 
// This is allowed: modifying a property
config.theme = "light";
config.language = "en";
console.log(config); // { theme: "light", fontSize: 16, language: "en" }
 
// This is NOT allowed: reassigning the variable
// config = { theme: "blue" }; // TypeError: Assignment to constant variable

Variable Scope: Where Variables Are Accessible

Scope determines where in your code a variable can be accessed. Understanding scope prevents bugs caused by variables leaking into areas where they should not exist.

Block Scope (let and const)

Variables declared with let and const exist only inside the curly braces {} where they are declared.

javascriptjavascript
const temperature = 35;
 
if (temperature > 30) {
  const message = "It's hot outside!";
  let warningLevel = "high";
  console.log(message);      // "It's hot outside!"
  console.log(warningLevel); // "high"
}
 
// console.log(message);      // ReferenceError: message is not defined
// console.log(warningLevel); // ReferenceError: warningLevel is not defined
// Both variables are inaccessible outside the if block

Function Scope (var)

Variables declared with var are accessible anywhere inside the function where they are declared, regardless of block boundaries.

javascriptjavascript
function processOrder(items) {
  if (items.length > 0) {
    var discount = 0.1; // var ignores block scope
  }
  // discount is accessible here because var is function-scoped
  console.log(discount); // 0.1
}
 
processOrder(["laptop", "mouse"]);

Global Scope

Variables declared outside any function or block are global and accessible everywhere.

javascriptjavascript
// Global variables (accessible everywhere)
const APP_NAME = "RuneHub";
let visitorCount = 0;
 
function incrementVisitor() {
  visitorCount += 1; // Can access global variable
  console.log(`${APP_NAME} visitor #${visitorCount}`);
}
 
incrementVisitor(); // "RuneHub visitor #1"
incrementVisitor(); // "RuneHub visitor #2"

Reassignment and Mutation

Understanding the difference between reassignment (changing what the variable points to) and mutation (changing the contents of what it points to) is essential.

javascriptjavascript
// REASSIGNMENT: changing the variable's value entirely
let count = 5;
count = 10; // Reassignment: count now holds 10
 
// const prevents reassignment
const limit = 100;
// limit = 200; // TypeError: Assignment to constant variable
 
// MUTATION: changing the internals of a reference type
const cart = ["apple", "banana"];
cart.push("cherry"); // Mutation: modifying the array's contents
console.log(cart);   // ["apple", "banana", "cherry"]
// This works because we did not reassign cart,
// we changed the contents of the array it references
 
// Reassignment vs mutation with objects
const settings = { volume: 50 };
settings.volume = 80;        // Mutation: OK with const
// settings = { volume: 80 }; // Reassignment: Error with const

Practical Patterns for Using Variables

Pattern 1: Accumulator

javascriptjavascript
// Building up a result step by step
const items = [
  { name: "Notebook", price: 12.99 },
  { name: "Pen Set", price: 8.49 },
  { name: "Backpack", price: 45.00 },
  { name: "Calculator", price: 24.99 }
];
 
let totalCost = 0; // Accumulator: will be reassigned, so use let
 
for (const item of items) {
  totalCost += item.price;
}
 
const TAX_RATE = 0.08; // Constant: will not change
const tax = totalCost * TAX_RATE;
const finalTotal = totalCost + tax;
 
console.log(`Subtotal: $${totalCost.toFixed(2)}`);  // $91.47
console.log(`Tax: $${tax.toFixed(2)}`);              // $7.32
console.log(`Total: $${finalTotal.toFixed(2)}`);     // $98.79

Pattern 2: Configuration Object

javascriptjavascript
// Use const for configuration objects: the reference stays constant
const appConfig = {
  apiBaseUrl: "https://api.example.com",
  maxRetries: 3,
  timeoutMs: 5000,
  features: {
    darkMode: true,
    notifications: true,
    analytics: false
  }
};
 
// Access and use configuration values
function fetchData(endpoint) {
  const url = `${appConfig.apiBaseUrl}${endpoint}`;
  const timeout = appConfig.timeoutMs;
  console.log(`Fetching ${url} with ${timeout}ms timeout`);
}
 
fetchData("/users"); // "Fetching https://api.example.com/users with 5000ms timeout"

Pattern 3: Conditional Assignment

javascriptjavascript
// Assign different values based on conditions
const hour = new Date().getHours();
 
let period;
if (hour < 12) {
  period = "morning";
} else if (hour < 17) {
  period = "afternoon";
} else {
  period = "evening";
}
 
// Shorter version with ternary operator
const isMorning = hour < 12 ? "Yes" : "No";
 
// Default values with nullish coalescing
const userTheme = null;
const activeTheme = userTheme ?? "system"; // "system" (because userTheme is null)
 
console.log(`Good ${period}! Theme: ${activeTheme}`);

Best Practices

Default to const for every variable. Only switch to let when you genuinely need to reassign the value. This makes your code easier to read because anyone scanning it knows that const values will not change.

Use descriptive, meaningful names. A variable named userSubscriptionStatus tells you exactly what it holds. A variable named x or temp forces everyone (including your future self) to trace through the code to understand its purpose.

Declare variables close to where they are used. Placing a variable declaration 50 lines before its first use makes the code harder to follow. Declare each variable as close as possible to the code that reads or modifies it.

Initialize variables at declaration. Declaring a variable without a value (let total;) creates an undefined value that can cause subtle bugs. Whenever possible, assign a meaningful initial value at declaration time.

Use UPPER_SNAKE_CASE for true constants. Values that are known at write time and never change (API URLs, configuration limits, mathematical constants) should use UPPER_SNAKE_CASE to signal their intent: const MAX_FILE_SIZE = 5242880;.

Common Mistakes and How to Avoid Them

Variable Declaration Pitfalls

These mistakes cause real bugs in beginner and intermediate codebases.

Declaring variables without a keyword. In non-strict mode, count = 5; (without let, const, or var) creates an accidental global variable. Always use a keyword. Enable strict mode ("use strict";) to catch this as an error.

Using const when you need to reassign. If a value changes inside a loop or conditional, declare it with let. Trying to reassign a const variable throws a TypeError at runtime.

Assuming const makes objects immutable. const prevents reassignment, not mutation. If you need a truly immutable object, use Object.freeze(), though it only applies to the top level (shallow freeze).

Shadowing variables unintentionally. Declaring a new variable with the same name in an inner scope "shadows" the outer variable, making the outer one inaccessible inside that block. This can cause bugs that are hard to trace.

javascriptjavascript
const name = "Alice";
 
function greet() {
  const name = "Bob"; // Shadows the outer 'name'
  console.log(name);  // "Bob" (not "Alice")
}
 
greet();
console.log(name); // "Alice" (outer variable unaffected)

Next Steps

Learn [variable naming](/tutorials/programming-languages/javascript/javascript-variable-naming-conventions-rules) conventions

Explore JavaScript variable naming conventions and rules to write code that is consistent, readable, and follows industry standards.

Understand variable scope in depth

Dive deeper into global vs local variables to understand how scope affects variable accessibility across functions and blocks.

Compare var, let, and const

Read the detailed comparison of var vs let vs const to understand hoisting, the temporal dead zone, and why modern JavaScript prefers let and const.

Learn JavaScript data types

Variables store data, so understanding JavaScript's type system (strings, numbers, booleans, objects, arrays) is the natural next step in your learning journey.

Rune AI

Rune AI

Key Insights

  • Default to const: Use const for every variable and switch to let only when you need reassignment; avoid var entirely
  • Scope matters: let and const are block-scoped (limited to {}), while var is function-scoped (leaks out of blocks)
  • const prevents reassignment, not mutation: Objects and arrays declared with const can have their contents modified; only the variable binding is locked
  • Initialize at declaration: Always assign a value when you declare a variable to avoid undefined bugs
  • Descriptive names: Clear, meaningful variable names make your code self-documenting and reduce the need for comments
RunePowered by Rune AI

Frequently Asked Questions

What is the difference between let and const?

`let` allows you to reassign the variable to a new value after declaration (`let x = 1; x = 2;`). `const` does not allow reassignment; the variable must keep the same value (or reference) for its entire lifetime. Both are block-scoped and were introduced in ES6 (2015).

Can I use var in modern JavaScript?

Technically yes, but you should avoid it. `var` has function-level scope instead of block scope, which leads to unexpected behavior in loops and conditionals. It also hoists differently than `let` and `const`. Modern codebases use `let` and `const` exclusively.

Why does const allow modifying object properties?

`const` prevents **reassignment** of the variable binding, not mutation of the value. When a `const` variable holds an object, the variable always points to the same object, but the object's properties can change. To prevent property changes, use `Object.freeze()`.

What happens if I declare a variable without let, const, or var?

In non-strict mode, the assignment creates an implicit global variable, which is almost always a bug. In strict mode (`"use strict";`), it throws a `ReferenceError`. Always use a keyword when declaring variables.

How many variables should I declare per line?

One. While JavaScript allows multiple declarations per line (`let a = 1, b = 2, c = 3;`), declaring one variable per line improves readability, makes version control diffs cleaner, and reduces the chance of errors when adding or removing variables.

Conclusion

JavaScript variables are the building blocks of every program you will write. Choosing between const and let communicates intent to anyone reading your code: const signals a value that will not be reassigned, while let signals a value that changes over its lifetime. Understanding declaration, initialization, scope, and the difference between reassignment and mutation gives you a solid foundation for writing clear, bug-free JavaScript.