Open almost any JavaScript file and you will see the same building blocks: a name, a value, and rules about what you are allowed to do next.
JavaScript is dynamically typed — a variable does not lock to one type at declaration. You can assign a number, then later assign a string. That flexibility is a feature and a footgun.
A variable is a labeled box. The type is whatever you put in it today.
If you are coming from Go, read Why Go Doesn't Let Variables Stay Uninitialized for the opposite design: types fixed early, zero values by default.
Quick poll
When you declare a variable, which keyword do you use most?
Tap an option — results stay on this device only.
Remember this one line
Default to const. Use let when you reassign. Avoid var.
Everything else — types, typeof, null, undefined — hangs off that habit.
const, let, and var
Three keywords, three different sets of rules. Not interchangeable.
Three ways to declare
const
- Scope
- Block — only inside `{ }` where it was declared
- Reassign?
- No — the binding cannot point somewhere else
- Reach for it when
- Default choice. Names that should not be reassigned.
const maxRetries = 3
const items = []
items.push("a") // okWatch out. const arr = [] — you cannot do arr = [1], but arr.push(1) still works. const freezes the binding, not deep immutability.
Sticky idea: Block scope (const / let) matches how you read code — what you declare inside an if stays inside that if.
The main types
JavaScript has seven primitive types plus objects. You do not need every edge case on day one — you need the ones that show up in bugs.
Primitive and object types
number
42, 3.14, NaN
All numbers are floats under the hood. Math just works until you hit precision limits.
Watch out. 0.1 + 0.2 !== 0.3. Use integers (cents) or a decimal library when money matters.
Sticky idea: typeof is a quick check, not a contract. For real safety, use TypeScript or validate at boundaries.
null vs undefined
Both mean “no useful value” in conversation. In code they tell different stories.
null vs undefined
undefined
The language never got a value — or the property does not exist.
Use when. Default for `let x`, missing object keys, functions with no return.
let total // undefined
const cfg = {}
cfg.port // undefinedSticky rule. Both are falsy, but they mean different things. Use === and be explicit in APIs — optional fields as undefined, intentional emptiness as null.
typeof in practice
typeof 42 // "number"
typeof "hello" // "string"
typeof true // "boolean"
typeof undefined // "undefined"
typeof null // "object" ← historic quirk
typeof {} // "object"
typeof [] // "object"
typeof (() => {}) // "function"Use typeof for quick debugging. For production checks, prefer strict equality and schema validation at API edges.
In real code
Prefer const until you cannot
const userId = session.id
const items = await fetchCart(userId)
let total = 0
for (const item of items) {
total += item.price * item.qty
}userId and items never get reassigned — const. total grows — let.
Sticky idea: If you never reassign, const documents intent for the next reader.
Do not use truthiness for business rules
// risky — 0 and "" are falsy
if (discount) {
apply(discount)
}
// clearer
if (discount != null && discount > 0) {
apply(discount)
}Sticky idea: Falsy is not the same as “invalid input.” Be explicit when zero or empty string are valid.
Objects hold shape; primitives hold values
const order = {
id: "ord_9912",
qty: 2,
shipped: false,
}
order.shipped = true // ok — mutating property
// order = {} // error if order is constSticky idea: const stops rebinding the variable. It does not freeze the object inside.
Template literals beat concatenation
const name = "Ada"
const greeting = `Hello, ${name}!`Backticks when you embed values. Regular quotes for plain strings.
Try this
- Rewrite one
varin an old file asconstorlet. Notice scope differences. - Log
typeof nullandtypeof []. Remember both say"object". - Write a function that returns nothing — log the result. That is
undefined. - Set a variable to
nullon purpose. Explain in a comment why null fits better than undefined. - Run
0.1 + 0.2in the console. See why money often uses integer cents.
Take these home
constby default — reassign only withlet.- Avoid
var— function scope leaks in ways block scope does not. - Dynamic typing — the type lives in the value, not the declaration.
undefined= never set / missing ·null= intentionally empty.typeof nullis"object"— use=== nullwhen you mean null.- Truthy/falsy is convenient in
if— dangerous for domain rules without explicit checks.
JavaScript gives you a small toolkit and a lot of rope. Names (const / let), types (primitives and objects), and the null/undefined split are the knots worth learning first — everything else in the language tends to hang off them.