JavaScript lesson 2 of 9
JavaScript Variables and Data Types
Understand let and const, JavaScript's primitive types, and how typeof, undefined, and null behave when you check and convert values.
Published · Every example on this page was run before it was published.
Every program you will ever write has to remember something. A game remembers your score, a checkout page remembers the price of what is in your cart, a weather app remembers this morning's temperature. JavaScript's tool for remembering is the variable, and the kind of thing being remembered — a number, a piece of text, a yes-or-no answer — is its data type. These two ideas sit underneath every other thing you will learn, so it is worth getting them exactly right before moving on.
Declaring Variables with let and const
You create a variable with let or const, followed by a name, an equals sign, and a value. let
creates a binding you can change later. const creates a binding you cannot reassign once it is set.
let temperature = 21.5;
const city = "Lisbon";
console.log(city);
console.log(temperature);Lisbon
21.5Because temperature was declared with let, you are free to point it at a new value later, and
JavaScript works out the right-hand side first, then attaches the name to the result:
let minutes = 90;
minutes = minutes + 30;
console.log(minutes);120const, on the other hand, refuses a second assignment outright:
const pi = 3.14;
pi = 3.14159;TypeError: Assignment to constant variable.That refusal only applies to the binding itself, not to whatever the binding points at. If a const
holds an array or an object, you can still change what is inside it — you simply cannot make the name
point at a different array or object:
const scores = [10, 20];
scores.push(30);
console.log(scores);[ 10, 20, 30 ]scores never stopped pointing at the same array; the array itself just grew. Writing
scores = [10, 20, 30] afterward, by contrast, would fail exactly like the pi example above, because
that really would be pointing scores at a different array.
Given the choice, prefer const. Reach for let only when you already know a variable's value needs
to change later, such as a running total or a loop counter. You may also see an older keyword, var,
in code written before 2015 — it behaves differently in ways that cause real bugs, and modern
JavaScript has no reason to use it, so this site does not either.
Naming Rules and Conventions
JavaScript enforces a short list of rules about what a name may look like. A name may contain letters,
digits, dollar signs, and underscores. It may not start with a digit, and it may not contain a space,
a hyphen, or most other punctuation. Names are case-sensitive, meaning score and Score are two
completely different variables. Finally, a name cannot be one of JavaScript's reserved words — words
such as let, if, class, and return that the language has claimed for its own grammar.
Beyond those hard rules, JavaScript programmers follow a shared convention called camelCase: the first word is lowercase, and every word after it starts with a capital letter, with no underscores or spaces at all.
let userName = "Ada";
let itemsInCart = 3;
let isLoggedIn = true;
console.log(userName, itemsInCart, isLoggedIn);Ada 3 trueNotice that a variable holding a true-or-false answer is conventionally named as a question the answer
fits — isLoggedIn rather than login. That habit makes code read like a sentence rather than a
puzzle.
Case sensitivity trips up beginners constantly, so it is worth seeing once:
let score = 10;
let Score = 99;
console.log(score);
console.log(Score);10
99The Primitive Types You Meet First
Every value in JavaScript has a type, and the typeof operator tells you which one you are holding at
any moment. Unlike a function, typeof does not need parentheses — it is written directly in front of
the value.
let count = 7;
let price = 4.99;
let name = "Ada";
let isReady = true;
let result;
console.log(typeof count);
console.log(typeof price);
console.log(typeof name);
console.log(typeof isReady);
console.log(typeof result);number
number
string
boolean
undefinedFive types are on display there. number covers every kind of number JavaScript has — whole or
decimal, positive or negative. Unlike some languages, JavaScript does not have a separate type for
whole numbers; 7 and 7.5 are both simply number:
console.log(typeof 7);
console.log(typeof 7.5);
console.log(7 === 7.0);number
number
truestring is text, written inside single quotes, double quotes, or backticks. boolean holds
exactly one of two values, true or false. And undefined is what you get automatically when a
variable is declared but never given a value — let result; on its own creates the variable and
leaves it empty, and undefined is JavaScript's own way of marking that emptiness. You did not have to
write undefined anywhere; JavaScript put it there for you.
undefined Versus null
JavaScript has a second "nothing here" value, null, and the difference between the two trips up
almost everyone at first. undefined means JavaScript has not been given a value yet. null means a
programmer deliberately assigned "no value" on purpose.
let empty = null;
console.log(empty);
console.log(typeof empty);null
objectThat second line is one of JavaScript's oldest quirks: typeof null reports "object", even though
null is not an object in any useful sense. This is a long-standing mistake baked into the language
itself, kept for backward compatibility, and every JavaScript developer simply learns to expect it. If
you need to check specifically for null, compare it directly with === null rather than trusting
typeof.
The two values are close enough that loose equality treats them as equal, while strict equality — which also checks the type — does not:
let a;
let b = null;
console.log(a == b);
console.log(a === b);true
falseAs a rule, use undefined for "this has not been set up yet" and reserve null for the cases where
you want to say, explicitly, "there is genuinely no value here."
Converting Between Types
A value's type does not change on its own, but you can build a new value of a different type out of
it using the built-in functions Number(), String(), and Boolean(). Each one leaves its input
untouched and hands back a fresh value.
let ageText = "34";
let age = Number(ageText);
console.log(age + 1);
console.log(typeof age);
console.log(typeof ageText);35
number
stringageText is still the string "34" afterward; Number() did not transform it in place. This matters
because converting text to a number is one of the most common conversions in real programs — anything a
person types into a form arrives as a string.
console.log(Number("abc"));
console.log(Number("42"));
console.log(String(12) + " birds");
console.log(Boolean(0));
console.log(Boolean("hi"));NaN
42
12 birds
false
trueNumber("abc") cannot make sense of letters as a number, so it returns NaN, short for "Not a
Number" — a special number value that signals a failed or meaningless calculation rather than throwing
an error outright. NaN is contagious: almost any arithmetic that touches it produces NaN too, which
makes it worth checking for with Number.isNaN() whenever a conversion might fail.
JavaScript Is Dynamically Typed
In some languages you must declare in advance that a variable holds a number, and it holds numbers
forever. JavaScript is dynamically typed: types belong to values, not to variable names, so a let
variable is free to be reassigned to a value of an entirely different type at any moment.
let box = 42;
console.log(typeof box);
box = "forty-two";
console.log(typeof box);
box = null;
console.log(typeof box);number
string
objectThis flexibility is convenient, but it moves a burden onto you: nothing warns you when a variable is
carrying a different type than you assumed. The classic case is text that looks like a number. The
string "3" and the number 3 are different values, and + treats them completely differently:
let quantity = "3";
console.log(quantity + quantity);
console.log(Number(quantity) + Number(quantity));
console.log(typeof (quantity + quantity));33
6
stringquantity + quantity concatenated two copies of the text "3" into "33", not 6. Nothing crashed
and nothing was flagged — the program simply computed a different answer than a careless reader might
expect, and carried on. This is exactly why any value arriving from outside your program — typed input,
data from a network request, text read from a file — deserves a deliberate conversion before you do
arithmetic with it.
A Worked Example
Here is a small, complete program that calculates a receipt line. It brings together let and const,
descriptive camelCase names, null, conversion from text, and template literals.
const itemName = "Notebook";
const unitPriceText = "3.75";
const quantityText = "4";
let discountCode = null;
const unitPrice = Number(unitPriceText);
const quantity = Number(quantityText);
const subtotal = unitPrice * quantity;
const hasDiscount = discountCode !== null;
let total;
if (hasDiscount) {
total = subtotal * 0.9;
} else {
total = subtotal;
}
console.log(`Item: ${itemName}`);
console.log(`Unit price: ${unitPrice}`);
console.log(`Quantity: ${quantity} (${typeof quantity})`);
console.log(`Subtotal: ${subtotal}`);
console.log(`Discount applied: ${hasDiscount}`);
console.log(`Total due: ${total}`);Item: Notebook
Unit price: 3.75
Quantity: 4 (number)
Subtotal: 15
Discount applied: false
Total due: 15Walking through it: the first four lines bind names to raw incoming data. Two of them end in Text
deliberately, as a reminder to the reader that those values are strings rather than numbers — exactly
the kind of data a form would hand you. discountCode is bound to null, which says "no discount was
supplied," a statement undefined could have made too, but null is the clearer choice when a
programmer is setting the absence on purpose.
The next block converts and calculates. Number(unitPriceText) builds the number 3.75 from the text
"3.75", and Number(quantityText) builds 4 from "4". Only after both conversions is it safe to
multiply them. Then discountCode !== null asks whether a code was actually supplied and stores the
answer as a boolean in hasDiscount. The if statement reads that boolean and decides what total
becomes — both branches are free to assign the same let variable, because total was declared once,
above the if, precisely so both branches could reach it.
Notice Subtotal: 15, not 15.0 or 15.00. Since JavaScript has only one numeric type, a whole-number
result simply prints as a whole number — there is no separate "this is technically a float" marker to
show. The final template literal, ${typeof quantity}, proves that quantity really did become a
number and not just text that looks numeric.
Common Mistakes
Redeclaring a variable with let or const
let count = 5;
let count = 10;SyntaxError: Identifier 'count' has already been declaredUnlike reassigning a value, declaring the same name twice with let or const in the same scope is
not allowed at all. This is a SyntaxError, which means JavaScript refuses to run the file — not even
the working line above the broken one executes. If you need a new value, drop the second let and just
assign: count = 10;.
Reassigning a const
const maxUsers = 10;
maxUsers = 20;TypeError: Assignment to constant variable.This is the single most common const-related error, and the fix is almost always to decide, honestly,
whether the value was ever supposed to change. If it was, declare it with let from the start rather
than switching later.
Reading a variable before its declaration runs
console.log(price);
let price = 9.99;ReferenceError: Cannot access 'price' before initializationlet and const variables exist in a kind of limbo, called the temporal dead zone, from the top
of their scope until the line that declares them actually runs. Referring to the name anywhere in that
gap is an error rather than quietly giving you undefined. In practice this almost only bites you when
a variable is used on a line above where you meant to declare it — reordering the two lines fixes it
completely.
Next Steps
You now have the two building blocks every JavaScript program is assembled from: names bound to values
with let or const, and values that carry a type. The Two Number Sum practice problem is a
natural place to apply them — it hands you numbers, asks you to combine them toward a target, and
rewards clear variable names and a firm grasp of when a value is a number rather than a string. Before
you attempt it, open the JavaScript playground and retype a few examples
from this lesson, changing the values as you go. Try calling typeof on a result that surprises you,
and try converting a string that cannot become a number, so that you recognise NaN on sight when it
turns up in your own code.
When you want a harder one
Interview-style problems graded against hidden tests — a big step up from the exercises. Come back to these when the ideas in this lesson feel comfortable rather than new.