Chapter 3: JS Data Types & Variables
Master the building blocks of JavaScript: modern variable declarations (var, let, const), the 8 fundamental data types, Stack vs Heap memory allocation, the Temporal Dead Zone (TDZ), and type coercion rules.
3.1 Understanding Variables & Identifiers
In JavaScript, a variable is a named container in memory used to store and reference data. You declare a variable once and use its identifier name to retrieve, manipulate, or pass that data throughout your program.
- Names can contain letters (
a-z,A-Z), digits (0-9), underscores (_), and dollar signs ($). - Names must begin with a letter,
$, or_. They cannot start with a digit (e.g.,1useris invalid). - Names are strictly case-sensitive (
userScore≠userscore). - Reserved JavaScript keywords cannot be used as variable names (e.g.,
let,class,function,return). - Convention: Always use camelCase for variable names (e.g.,
firstName,totalCartPrice).
Declaring Variables in JavaScript
// 1. const: Used for constants and immutable bindings (Default recommendation)
const maxLoginAttempts = 5;
const siteName = "AICodeLab";
// 2. let: Used when a variable's value must change over time
let currentScore = 0;
currentScore += 10; // score is now 10
// 3. var: Legacy ES5 declaration (Avoid in modern codebases)
var legacySessionId = "xyz-994";
Try it Yourself
3.2 var vs let vs const — Deep Dive
Before ES6 (2015), JavaScript only had the var keyword. ES6 introduced let and const to eliminate common bugs related to scoping, hoisting, and accidental variable overrides.
| Feature | const (Recommended) |
let (For Reassignment) |
var (Legacy — Avoid) |
|---|---|---|---|
| Scope | Block Scope { ... } |
Block Scope { ... } |
Function / Global Scope |
| Re-assignable? | ❌ No (Throws TypeError) | ✅ Yes | ✅ Yes |
| Re-declarable? | ❌ No (Throws SyntaxError) | ❌ No (Throws SyntaxError) | ⚠️ Yes (Bug-prone) |
| Hoisting & TDZ | Hoisted into Temporal Dead Zone | Hoisted into Temporal Dead Zone | Hoisted & initialized to undefined |
| Window Property | Does not attach to window |
Does not attach to window |
Attaches to window.varName |
Block Scope (let & const)
if (true) {
let blockVariable = "Inside";
const pi = 3.14159;
}
// ❌ ReferenceError: blockVariable is not defined
console.log(blockVariable);
Function Scope Leak (var)
if (true) {
var leakedVariable = "Leaked!";
}
// ⚠️ Works! "var" leaks outside if blocks!
console.log(leakedVariable); // Output: "Leaked!"
Unlike var (which initialises to undefined immediately upon hoisting), let and const remain uninitialised in the TDZ until execution reaches their declaration line.
3.4 The 8 JavaScript Data Types
JavaScript values are categorized into two fundamental groups: 7 Primitive Types (immutable, stored directly by value) and 1 Reference Type (mutable, stored in heap memory by reference).
Textual data enclosed in quotes or backticks.
"Hello" 'World' `Hi ${name}`
64-bit IEEE 754 floats, integers & special numbers.
42, 3.14, -0, NaN, Infinity
Arbitrary-precision integers beyond 2^53 - 1.
9007199254740995n
Logical values representing truthiness.
true, false
Variable declared but has not been assigned a value.
let x; // undefined
Explicit representation of 'no value' or 'empty'.
let user = null;
Unique, immutable identifier for object keys.
Symbol('id')
Collections of key-value pairs, Arrays & Functions.
{a: 1}, [1, 2], fn()
Primitives (numbers, booleans, strings) are stored directly on the Stack. Objects & Arrays live on the Heap; their variables hold a reference memory address pointer.
3.6 Dynamic Typing & The typeof Operator
JavaScript is a dynamically typed language. Variables are not bound to a fixed type; rather, the data value assigned to them dictates their type, which can change dynamically at runtime.
Using the typeof Operator
typeof "Hello" // "string"
typeof 42 // "number"
typeof true // "boolean"
typeof undefined // "undefined"
typeof 100n // "bigint"
typeof Symbol("id") // "symbol"
typeof { a: 1 } // "object"
typeof [1, 2, 3] // "object" (Arrays are special objects!)
typeof function(){} // "function" (Callable object)
// ⚠️ Famous Historical JavaScript Quirk:
typeof null // "object" (Legacy bug from JS 1.0 that cannot be fixed without breaking the web!)
typeof NaN // "number" ("Not a Number" is still typed as Number!)
Try it Yourself
3.7 Type Coercion & Conversion Rules
Implicit Coercion occurs automatically when operators expect a certain type. Explicit Conversion is when you intentionally convert types using built-in constructors.
Explicit Conversion (Safe)
// Convert to Number
Number("42") // 42
Number("abc") // NaN
parseInt("20px") // 20
// Convert to String
String(123) // "123"
(123).toString() // "123"
// Convert to Boolean
Boolean(1) // true
Boolean(0) // false
Boolean("") // false
Boolean("hello") // true
Implicit Coercion (Gotchas)
// Plus operator favors string concatenation!
"5" + 2 // "52" (String)
"5" - 2 // 3 (Number!)
"5" * "2" // 10 (Number!)
true + 1 // 2 (true becomes 1)
false + 1 // 1 (false becomes 0)
// Loose (==) vs Strict (===) Equality
"5" == 5 // true (Implicitly coerces!)
"5" === 5 // false (Strictly checks type!)
Declare variable values below to watch JavaScript dynamically inspect its data type, determine its memory allocation, and test type coercion live:
Safe User Profile Sanitizer
Problem: When receiving user profile data from external form inputs, values are often strings (e.g. age string "24") or missing (undefined). Write a function that safely normalizes raw user inputs into proper JavaScript types:
- Extract raw name (String) and trim leading/trailing whitespace.
- Convert
ageinto a strict Number integer. If invalid, fallback to0. - Cast
isSubscribed(which may be"true"or1) into a strict Boolean. - Return an immutable object with sanitized types.
Click to Reveal Solution Code
function sanitizeProfile(rawInput) {
return {
name: String(rawInput.name || "").trim(),
age: parseInt(rawInput.age, 10) || 0,
isSubscribed: Boolean(rawInput.isSubscribed === true || rawInput.isSubscribed === "true" || rawInput.isSubscribed === 1),
sanitizedAt: new Date()
};
}
// Test Run:
const rawUser = { name: " Sarah Connor ", age: "28", isSubscribed: "true" };
const cleanUser = sanitizeProfile(rawUser);
console.log(cleanUser);
// Output: { name: "Sarah Connor", age: 28, isSubscribed: true, sanitizedAt: ... }