Skip to content

Variables and Data Types

💡
Before you start

You need Node installed, and to know how to run a .js file. If node --version in a terminal prints a version number, you are ready. If it does not — or if you have never opened a terminal — do Getting Started with JavaScript first; it installs Node and runs your first program in about fifteen minutes. Nothing else is needed.

What Are Variables?

A variable is a named container that holds a value. Think of it as a labeled box where you store data that your program needs to remember. In JavaScript, you create variables using special keywords: let, const, or var.

let name = "Alice";
const age = 25;
var city = "London";

console.log(name);  // "Alice"
console.log(age);   // 25
console.log(city);  // "London"

Unlike Python where you simply write name = "Alice", JavaScript requires a declaration keyword. This tells the engine how the variable should behave — whether it can be reassigned, and what scope it lives in.

Variable Naming Rules

  • Must start with a letter, underscore (_), or dollar sign ($)
  • Can contain letters, numbers, underscores, and dollar signs
  • Are case-sensitive (Name and name are different)
  • Cannot be reserved words (let, class, return, etc.)
  • Convention: use camelCase for variables and functions (userName, totalPrice)
// Good variable names
let userName = "Alice";
let totalPrice = 49.99;
let isLoggedIn = true;
let _privateVar = "internal";
let $element = "DOM node";

// Bad variable names (will cause errors)
// let 2fast = "no";       // can't start with a number
// let my-name = "no";     // hyphens not allowed
// let let = "no";         // reserved word

let vs const vs var

let — Reassignable Block-Scoped Variable

Use let when the value will change. It is block-scoped, meaning it only exists inside the nearest { } block.

let score = 0;
score = 10;        // allowed — reassignment is fine
score = score + 5; // score is now 15

let message = "hello";
message = "goodbye"; // allowed

const — Constant Block-Scoped Variable

Use const when the value should never be reassigned. It must be initialized when declared.

const PI = 3.14159;
const MAX_USERS = 100;
const API_URL = "https://api.example.com";

// PI = 3.14;  // TypeError: Assignment to constant variable
💡
Prefer const by default

Use const for every variable unless you know it needs to be reassigned. This makes your code easier to reason about — when you see const, you know the binding will never change. Only switch to let when reassignment is actually needed. Note that const prevents reassignment of the variable, but objects and arrays declared with const can still have their contents modified.

// const prevents reassignment, not mutation
const colors = ["red", "green", "blue"];
colors.push("yellow");     // allowed — modifying the array
// colors = ["new array"]; // TypeError — reassigning the variable

const user = { name: "Alice" };
user.name = "Bob";         // allowed — modifying a property
// user = { name: "Bob" }; // TypeError — reassigning the variable

var — The Legacy Keyword

var is the original way to declare variables in JavaScript. It is function-scoped (not block-scoped), which leads to confusing behavior. Modern code should use let and const instead.

// var is function-scoped, not block-scoped
if (true) {
    var leaked = "I'm visible outside!";
    let contained = "I stay inside";
}
console.log(leaked);     // "I'm visible outside!" — var leaks out
// console.log(contained); // ReferenceError — let stays in the block

// var allows redeclaration (confusing!)
var name = "Alice";
var name = "Bob";   // no error — silently overwrites
console.log(name);  // "Bob"

// let does not allow redeclaration
let age = 25;
// let age = 30;    // SyntaxError: already declared

Data Types

JavaScript has seven primitive data types and one complex type (Object). Here are the primitives you will use most often:

String

Strings represent text. They can be wrapped in single quotes, double quotes, or backticks:

const single = 'Hello';
const double = "World";
const backtick = `Hello, ${double}`; // template literal

// String properties and methods
const greeting = "Hello, World!";
console.log(greeting.length);          // 13
console.log(greeting.toUpperCase());   // "HELLO, WORLD!"
console.log(greeting.toLowerCase());   // "hello, world!"
console.log(greeting.includes("World")); // true
console.log(greeting.indexOf("World"));  // 7
console.log(greeting.slice(0, 5));       // "Hello"
console.log(greeting.replace("World", "JavaScript")); // "Hello, JavaScript!"
console.log(greeting.split(", "));       // ["Hello", "World!"]

Number

JavaScript has a single number type for both integers and decimals (unlike Python which separates int and float):

const integer = 42;
const decimal = 3.14;
const negative = -10;
const big = 1_000_000;  // underscores for readability (same as 1000000)

// Arithmetic operations
console.log(10 + 3);    // 13
console.log(10 - 3);    // 7
console.log(10 * 3);    // 30
console.log(10 / 3);    // 3.3333333333333335
console.log(10 % 3);    // 1 (remainder)
console.log(10 ** 3);   // 1000 (exponentiation)

// Special number values
console.log(Infinity);          // Infinity
console.log(-Infinity);         // -Infinity
console.log(0 / 0);            // NaN (Not a Number)
console.log(isNaN("hello"));   // true
console.log(Number.isFinite(42)); // true

Boolean

Booleans represent true or false (lowercase in JavaScript, unlike Python's True/False):

const isLoggedIn = true;
const isAdmin = false;

// Comparison operators return booleans
console.log(5 > 3);     // true
console.log(10 === 10);  // true
console.log(5 !== 3);    // true
console.log(5 >= 5);    // true
console.log(3 < 1);     // false

// Logical operators
console.log(true && false);  // false (AND — both must be true)
console.log(true || false);  // true  (OR — at least one true)
console.log(!true);          // false (NOT — inverts the value)

null and undefined

These two types represent "absence of value," but they differ in intent:

// undefined — variable declared but not assigned
let x;
console.log(x);        // undefined

// null — intentionally set to "no value"
let user = null;       // explicitly means "no user yet"
console.log(user);     // null

// The difference:
// undefined = "hasn't been given a value yet"
// null = "deliberately set to empty"

console.log(typeof undefined); // "undefined"
console.log(typeof null);      // "object" (this is a known JavaScript quirk)

Symbol

Symbols are unique identifiers. They are an advanced feature used primarily for object property keys that should never collide:

const id1 = Symbol("id");
const id2 = Symbol("id");

console.log(id1 === id2);  // false — every Symbol is unique
console.log(typeof id1);   // "symbol"

Type Checking with typeof

Use the typeof operator to check what type a value is. It returns a string:

console.log(typeof "hello");     // "string"
console.log(typeof 42);          // "number"
console.log(typeof 3.14);        // "number" (no separate float type)
console.log(typeof true);        // "boolean"
console.log(typeof undefined);   // "undefined"
console.log(typeof null);        // "object" (historical bug, never fixed)
console.log(typeof Symbol("x")); // "symbol"
console.log(typeof {});          // "object"
console.log(typeof []);          // "object" (arrays are objects!)
console.log(typeof function(){}); // "function"

// To check for arrays specifically:
console.log(Array.isArray([1, 2, 3]));  // true
console.log(Array.isArray("hello"));    // false

Type Coercion and Comparison

JavaScript automatically converts types in certain situations. This is called type coercion, and it is one of the trickiest parts of the language.

Implicit Coercion

// String concatenation wins over addition
console.log("5" + 3);       // "53" (number coerced to string)
console.log("5" + true);    // "5true"

// Other operators convert to numbers
console.log("5" - 3);       // 2 (string coerced to number)
console.log("5" * 2);       // 10
console.log("5" / 1);       // 5
console.log(true + 1);      // 2 (true becomes 1)
console.log(false + 1);     // 1 (false becomes 0)

// Truthy and falsy values
// These are "falsy" (evaluate to false in boolean context):
// false, 0, -0, "", null, undefined, NaN
// Everything else is "truthy"

console.log(Boolean(0));          // false
console.log(Boolean(""));         // false
console.log(Boolean(null));       // false
console.log(Boolean("hello"));    // true
console.log(Boolean(42));         // true
console.log(Boolean([]));         // true (empty array is truthy!)

== vs === (Loose vs Strict Equality)

⚠️
Always use === and !== (strict equality)

The loose equality operator == performs type coercion before comparing, which leads to surprising and error-prone results. The strict equality operator === compares both value and type without coercion. There is almost never a good reason to use == in modern JavaScript.

// Loose equality (==) — coerces types before comparing
console.log(5 == "5");       // true  (string "5" converted to number)
console.log(0 == false);     // true  (false converted to 0)
console.log("" == false);    // true  (both coerce to 0)
console.log(null == undefined); // true (special case)
console.log(0 == "");        // true  (confusing!)

// Strict equality (===) — no coercion, must match type AND value
console.log(5 === "5");      // false (number vs string)
console.log(0 === false);    // false (number vs boolean)
console.log("" === false);   // false (string vs boolean)
console.log(null === undefined); // false (different types)
console.log(0 === "");       // false

// Same for inequality
console.log(5 != "5");      // false (loose — coerces, then equal)
console.log(5 !== "5");     // true  (strict — different types)

Explicit Type Conversion

// To String
console.log(String(42));        // "42"
console.log(String(true));      // "true"
console.log((42).toString());   // "42"

// To Number
console.log(Number("42"));     // 42
console.log(Number("3.14"));   // 3.14
console.log(Number(""));       // 0
console.log(Number("hello"));  // NaN
console.log(Number(true));     // 1
console.log(Number(false));    // 0
console.log(parseInt("42px")); // 42 (parses until non-digit)
console.log(parseFloat("3.14em")); // 3.14

// To Boolean
console.log(Boolean(1));       // true
console.log(Boolean(0));       // false
console.log(Boolean("text"));  // true
console.log(Boolean(""));      // false

Template Literals

Template literals (backtick strings) are JavaScript's answer to Python's f-strings. They let you embed expressions inside strings and create multi-line strings easily:

const name = "Alice";
const age = 25;

// String interpolation with ${}
const greeting = `Hello, ${name}! You are ${age} years old.`;
console.log(greeting);
// "Hello, Alice! You are 25 years old."

// Expressions inside ${}
console.log(`Next year you'll be ${age + 1}.`);
console.log(`Is adult: ${age >= 18 ? "yes" : "no"}`);
console.log(`Uppercase: ${name.toUpperCase()}`);

// Multi-line strings (preserves line breaks)
const html = `
<div class="card">
    <h2>${name}</h2>
    <p>Age: ${age}</p>
</div>
`;

// Without template literals, you'd need:
const oldWay = "Hello, " + name + "! You are " + age + " years old.";
// Much harder to read!

Now Do It Yourself: Five Steps

JavaScript has three ways to declare a variable and one famous trap about adding things together. You will meet all of it in ten minutes. Every output below is exactly what Node printed.

1
Declare with const and let, and see which one moves

Go: open a terminal, run cd, then create a file called vars.js.

Do: type these five lines and run node vars.js.

const name = "Alice";
let age = 25;
console.log(name, age);
age = 26;
console.log(age);

You should see: Alice 25 then 26. Use const by default and let only when the value genuinely has to change — that way anything that moves is visible at a glance.

If not: if nothing prints, check the file name and that you are in the right folder. var also exists and you will meet it in older code; it behaves differently around blocks and there is no reason to write new code with it.

2
Find out what const actually protects

Go: same file, replace the contents.

Do: type these two lines and run it. This is meant to fail.

const x = 1;
x = 2;

You should see: TypeError: Assignment to constant variable. The name is locked to that value.

If not: here is the part that surprises everyone: const locks the name, not the contents. const list = [1,2]; list.push(3); works perfectly — you did not reassign list, you changed what it points at. Only list = [9] is forbidden.

3
Meet the addition trap, on purpose

Go: same file, replace the contents.

Do: type these three lines and run it.

console.log("5" + 3);
console.log("5" - 3);
console.log(Number("5") + 3);

You should see: 53, then 2, then 8. Read that carefully. With +, JavaScript decided you meant to join text and turned 3 into "3". With -, joining makes no sense, so it turned "5" into a number instead. The language guesses, and it guesses differently per operator.

If not: there is nothing to fix — this is the single most common source of wrong numbers in JavaScript, and it appears the moment you read a value from a form or a URL, because both give you text. Convert deliberately with Number(...) and the guessing stops.

4
Check types instead of assuming them

Go: same file, replace the contents.

Do: type these four lines and run it.

console.log(typeof "5");
console.log(typeof 5);
console.log(typeof true);
console.log(typeof undefined);

You should see: string, number, boolean, undefined. When a calculation gives a strange answer, typeof is the first thing to reach for — it usually turns out something is text that you assumed was a number.

If not: one famous oddity to know rather than be caught by: typeof null returns "object". That is a bug from 1995 that can never be fixed without breaking the web. Test for null with value === null.

5
Build a string properly, with a template literal

Go: same file, replace the contents.

Do: type these four lines and run it. Those are backticks, not quotes — the key above Tab on most keyboards.

const first = "Alice";
const years = 25;
console.log("Old way: " + first + " is " + years);
console.log(`Better: ${first} is ${years}`);

You should see: Old way: Alice is 25 then Better: Alice is 25. Same result, and the second is far harder to get wrong — no stray +, no missing spaces, and it survives being edited later.

If not: SyntaxError almost always means you used ordinary quotes instead of backticks. ${...} only works inside backticks; inside normal quotes it is just those characters, printed literally.

🎉
Check yourself before moving on

Without scrolling up: a form field gives you "10" and you add 5. What do you get, and what do you actually want? Answer: "105", because + joins text. Convert first: Number("10") + 5 gives 15.

Now do it without the page: write a file that takes a price as text and a quantity as a number, and prints a correct total in a sentence. You need Number() from step 3 and a template literal from step 5 — and if the answer looks like a phone number, you skipped the conversion.

Summary

  • Use const by default, let when reassignment is needed, avoid var
  • String: text data — "hello", 'hello', or `hello`
  • Number: integers and decimals — 42, 3.14
  • Boolean: true or false
  • null: intentionally empty — null
  • undefined: declared but not assigned
  • Use typeof to check types, Array.isArray() for arrays
  • Always use === and !== for comparisons (strict equality)
  • Template literals (`${variable}`) are the cleanest way to build strings
🎉
Variables and types mastered!

You now understand how JavaScript stores and handles data. Next up: control flow — making your programs make decisions with if, else, switch, and loops.