DEV Community

Cover image for Variables in JavaScript 101
Petrina Ropra
Petrina Ropra

Posted on

Variables in JavaScript 101

Disclaimer: I am not a professional software engineer nor a computer science student. This is more of what I understand about variables in JavaScript from what I read on MDN Web Docs.


JavaScript Variables

A variable is like a label that points to a certain space in the computer's memory. When you assign a data type or object to a variable, it goes into that space.

Declaring Variables

A variable is declared using one of these three keywords: var, let or const.

  • var — unpredictable and highly recommended NOT to use
  • let — use only when you are 100% sure you will reassign a new value later on
  • const — the default choice; always use this unless you need to reassign

Naming Variables

There are a few rules and best practices to follow when naming variables:

  • Names can only start with a letter, underscore (_) or dollar sign ($) — any other character will throw an error
  • Names cannot contain spaces. For example, let my name = "Athena" is not allowed
  • Names are case sensitive — num, Num and NUM are three different variable names
  • Always make sure your variable name briefly describes what its value represents
  • Your variable names must not be the same as JavaScript keywords like;
let let = "hey";
//Error: let is not allowed to be used in variable declarations
Enter fullscreen mode Exit fullscreen mode

For variables with two words, use camelCase or underscores:

let myName = "Athena";   // camelCase
let my_name = "Athena";  // underscore
const MY_NAME = "Athena"; //for const it is recommended to use UPPERCASE_SNAKE_CASE
Enter fullscreen mode Exit fullscreen mode

Declaring Multiple Variables

You can declare two variables on the same line:

let num2 = 2, num4 = 4;
Enter fullscreen mode Exit fullscreen mode

However, for best practices declare them on separate lines to improve readability, like;

let num2 = 2; 
let num4 = 4;
Enter fullscreen mode Exit fullscreen mode

Reassigning Variables

A variable declared with let or var can have its value reassigned, but a variable declared with const cannot:

let num4 = 77;
num4 = 55;
console.log(num4);
// 55 — the value of num4 is now reassigned to 55

const num2 = 45;
num2 = 46;
console.log(num2);
// Uncaught TypeError: Assignment to constant variable.
Enter fullscreen mode Exit fullscreen mode

Also, you cannot create another variable or function with the same name as a const variable, making your code more predictable and less prone to bugs. This is why it is highly recommended to always use const by default — it prevents accidental reassignment and signals to other developers that a value won't change throughout your code.

Primitives vs Objects in Memory

A variable can only point to one value at a time, but that value can be a data structure such as an array or object that contains multiple values. Primitives are passed by value and objects are passed by reference.

Primitive data types — many variables can hold the same primitive value, but they are independent copies. Each copy takes up its own space in memory, so changing one never affects the others:

let num4 = 45;
let num5 = num4;
num4 = num4 + 5;
console.log(num4, num5);
// 50 45 — num5 is still 45 even though num4 changed
Enter fullscreen mode Exit fullscreen mode

Objects — many variables can label one object, but it is one single object in memory. Changing it through one variable affects all variables pointing to it:

let cup1 = { drink: "water" };
let cup2 = cup1;
console.log(cup1.drink, cup2.drink);
// water water

cup2.drink = "coffee";
console.log(cup1.drink, cup2.drink);
// coffee coffee — cup1 is also changed
Enter fullscreen mode Exit fullscreen mode

Analogy:
For primitive data types: think of a variable as a label on a cup, where the cup is the value. If you buy a second cup that looks identical to the first, it has its own separate label and takes up its own space in the cupboard — they are completely independent.

For objects: there is only one cup and multiple labels can be stuck onto that same cup. So when you fill or empty the cup, it affects everything pointing to it.

Mutating Objects Declared with const

While you cannot reassign a const variable to point to a new object, you can still change the contents of the object it points to:

//Example 1
const cup2 = { drink: "water" };
cup2.drink = "coffee";
console.log(cup2.drink);
// coffee — modifying a property is allowed

cup2 = { drink: "juice" };
console.log(cup2);
// Uncaught TypeError: Assignment to constant variable.
// — reassigning the variable itself is not allowed

//Example 2
const cup = ["1 tsp coffee", "2 tsp sugar"];
cup[0] = "1 tsp Milo";
console.log(cup[0]);
// 1 tsp Milo - modifying an item of the array is allowed

cup = ["juice", "ice"];
console.log(cup);
// Uncaught TypeError: Assignment to constant variable.
// — reassigning the variable itself is not allowed
Enter fullscreen mode Exit fullscreen mode

Analogy:
Think of the data structure or array as a cup, now when you change the contents in the cup you are not changing the cup itself but the contents it carries. So with const keyword you cannot change the cup itself but you can change the contents of the cup like whether it can have ice or not

There is a catch though. If you empty an array or object not through methods like pop() or splice() but like this:

const abc = ['a', 'b'];
abc = []; 
console.log(abc);
// Uncaught TypeError: Assignment to constant variable.
// — reassigning the variable itself is not allowed
Enter fullscreen mode Exit fullscreen mode

This error is thrown because the computer sees [ ] as a brand new empty array in memory, not a modification of the existing one. And it is right — you are not emptying the contents of the original array, you are pointing the variable - abc to a completely new empty data structure, which const does not allow.

Now that we understand how variables store and hold data, let us look at where in your program they can actually be accessed


Scope

JavaScript has four kinds of scope: global scope, module scope, function scope and block scope.

Global Scope

A global scope is the outermost part of a program. Any variable declared before a function, class, loop, or any other structure is in the global scope and can be accessed from anywhere in the program. A variable declared within the global scope is a global variable:

const greeting = "Hello";

function sayHello() {
    console.log(greeting); // ✅ accessible inside the function
}

if (true) {
    console.log(greeting); // ✅ accessible inside the if statement
}

sayHello();
console.log(greeting); // ✅ accessible outside everything
// Hello
Enter fullscreen mode Exit fullscreen mode

Module Scope

A variable declared within a module can only be accessed in that module. To use it elsewhere it must be explicitly exported and then imported:

// moduleA.js
const greeting = "Hello";
export default greeting; // has to be exported to be used elsewhere

// moduleB.js
console.log(greeting); // ❌ ReferenceError: greeting is not defined
// greeting is confined to moduleA.js and cannot be accessed here directly
import greeting from './moduleA.js'; // ✅ has to be imported first
console.log(greeting); // Hello
Enter fullscreen mode Exit fullscreen mode

Function Scope

A variable declared within a function is a local variable and can only be accessed inside that function. It cannot be accessed from outside:

function sayHello() {
    const greeting = "Hello";
    console.log(greeting); // ✅ accessible inside the function
}

sayHello();
console.log(greeting); // ❌ ReferenceError: greeting is not defined
Enter fullscreen mode Exit fullscreen mode

However, a variable declared within a function can be accessed by any inner if else statements or loops inside that same function:

function sayHello() {
    const greeting = "Hello";

    if (true) {
        console.log(greeting); // ✅ accessible inside the if statement
    }

    for (let i = 0; i < 3; i++) {
        console.log(greeting); // ✅ accessible inside the loop
    }
}

sayHello();
console.log(greeting); // ❌ ReferenceError: greeting is not defined
Enter fullscreen mode Exit fullscreen mode

Block Scope

A block scope is defined by a pair of curly braces {}, as seen in structures like if else statements and loops. Variables declared with let or const are confined to the block in which they are defined and cannot be accessed outside of it.

if (true) {
    const greeting = "Hello";
    console.log(greeting); // ✅ accessible inside the if statement
}
console.log(greeting); // ❌ ReferenceError: greeting is not defined

for (let i = 0; i < 3; i++) {
    const message = "Hi";
    console.log(message); // ✅ accessible inside the loop
}
console.log(message); // ❌ ReferenceError: message is not defined
Enter fullscreen mode Exit fullscreen mode

var however ignores block boundaries and leaks out into the surrounding scope, which is another reason why using var is strongly discouraged:

if (true) {
    var greeting = "Hello";
}
console.log(greeting); // ⚠️ Hello — var leaks outside the if statement

for (var i = 0; i < 3; i++) {
    // loop runs
}
console.log(i); // ⚠️ 3 — var leaks outside the loop
Enter fullscreen mode Exit fullscreen mode

A Note on Variable Naming Across Scopes

It is best practice to avoid using the same variable name in different scopes. It can be confusing both to yourself and to other developers reading your code. Note that this is mainly a concern when using letconst handles this for you by throwing an error if you try to declare a variable with the same name in the same scope.


Hoisting

When JavaScript runs your code, it processes variable declarations before executing anything else. This is called hoisting.

With var, the variable is hoisted and automatically set to undefined right away, meaning you can reference it before its declaration — though the value won't be useful until you actually assign something to it:

console.log(greeting); // ⚠️ undefined — no error thrown, but value is not yet assigned
var greeting = "Hello";
console.log(greeting); // Hello
Enter fullscreen mode Exit fullscreen mode

let and const behave differently. There is a period of time between when a scope starts and when a let or const variable is actually declared — this is called the Temporal Dead Zone (TDZ). During this period the variable exists but has not been initialized yet, so trying to access it throws a ReferenceError:

console.log(greeting); // ❌ ReferenceError: Cannot access 'greeting' before initialization
const greeting = "Hello";

console.log(message); // ❌ ReferenceError: Cannot access 'message' before initialization
let message = "Hi";
Enter fullscreen mode Exit fullscreen mode

This is actually a good thing — the TDZ forces you to declare your variables before using them, making your code more predictable and bugs easier to track down. It is yet another reason why var should be avoided in favour of let and const.

Unlike var, which only hoists the declaration but not its value, function declarations are hoisted entirely — meaning you can safely call a function anywhere within its scope, even before it appears in the code:

sayHello(); // ✅ Hello — works fine even though the function is declared below

function sayHello() {
    console.log("Hello");
}
Enter fullscreen mode Exit fullscreen mode

Function expressions follow the same hoisting rules as the variable keyword used to declare them — unlike function declarations which are hoisted entirely.

If declared with var — it is hoisted but only as undefined, so calling it before declaration throws a TypeError:

javascriptsayHello(); // ❌ TypeError: sayHello is not a function
var sayHello = function() {
    console.log("Hello");
}
Enter fullscreen mode Exit fullscreen mode

If declared with let or const — it falls in the TDZ, so calling it before declaration throws a ReferenceError:

javascriptsayHello(); // ❌ ReferenceError: Cannot access 'sayHello' before initialization
const sayHello = function() {
    console.log("Hello");
}
Enter fullscreen mode Exit fullscreen mode

To read more on variables in general you can check out this link from imarticus.org: Demystifying Variables: The Building Blocks of Programming

Top comments (0)