Skip to main content

🧠 Variables, Data Types & Operators

If HTML is the skeleton of a web page and CSS is its skin and clothes, JavaScript is the brain and muscles. In this first JavaScript lesson you'll learn how the language remembers things — the containers it stores data in, the kinds of data it understands, and the operators that push that data around.

Week 1 · Day 5 (Friday: Introduction to JavaScript) · Lecture 1

🎯 Learning Objectives

By the end of this lesson, you will be able to:

  • Add JavaScript to a web page three different ways and know which to prefer
  • Declare variables with let and const and explain why var is avoided
  • Identify JavaScript's seven primitive types and the object types
  • Convert between types deliberately and predict JavaScript's automatic coercion
  • Use arithmetic, comparison, logical, and ternary operators with confidence

Estimated Time: 60 minutes

Practice: Build a type-checker function and a small temperature converter.

In This Lesson

Why JavaScript?

JavaScript is the only programming language that runs natively in every web browser. It's what makes a page react: a button that responds to a click, a form that validates as you type, a feed that loads more posts as you scroll. Since the arrival of Node.js, the same language also runs on servers — which is exactly why this bootcamp can take you across the entire stack without switching languages.

graph TD A[JavaScript] --> B[Client-Side
in the browser] A --> C[Server-Side
with Node.js] B --> D[DOM Manipulation] B --> E[Event Handling] B --> F[Fetching Data] C --> G[Web Servers & APIs] C --> H[Databases] C --> I[Build Tools]

Today we stay on the ground floor: how JavaScript stores and manipulates data. Every interactive feature you'll ever build rests on the fundamentals in this lesson.

Adding JavaScript to HTML

Before code can run, the browser has to find it. There are three ways to attach JavaScript to a page — in rough order from "avoid" to "do this."

1. Inline (avoid)

<button onclick="alert('Hello!')">Click me</button>

👎 Mixes behavior into your markup and can't be reused. Fine for a throwaway demo, wrong for real projects.

2. Internal

<script>
    console.log('Hello, JavaScript!');
</script>

👍 Acceptable for small, page-specific snippets.

3. External (best)

<script src="script.js" defer></script>
<script type="module" src="app.js"></script>

👍👍 Reusable, cacheable, and keeps logic out of your HTML.

📖 defer vs async

defer downloads the script in parallel but runs it only after the HTML is parsed, in order — the safe default. async runs each script the moment it finishes downloading, in no guaranteed order — good for independent third-party scripts like analytics.

Variables: let, const & var

A variable is a labeled box you put a value in so you can refer to it by name later. JavaScript gives you three keywords to create one — but in modern code you'll use only two.

Three variable boxes: const is sealed, let can be refilled, var is legacy const 3.14159 🔒 cannot reassign let count = 0 → 1 🔄 can reassign var function-scoped ⚠️ legacy — avoid
Reach for const first, let when a value must change, and leave var in the past.

const — your default

const PI = 3.14159;
// PI = 3; // ❌ TypeError: Assignment to constant variable

// "const" locks the binding, not the contents:
const user = { name: "Ada" };
user.name = "Grace";  // ✅ allowed — same object, new property value
// user = {};          // ❌ not allowed — that's a new binding
💡 Rule of thumb: Declare everything const until the code forces you to reassign it. Then, and only then, switch it to let.

let — when a value changes

let score = 0;
score = score + 10;   // ✅ reassignment is the whole point

// Both let and const are block-scoped:
let x = 1;
if (true) {
    let x = 2;         // a different x, living only inside these braces
    console.log(x);    // 2
}
console.log(x);        // 1

var — the one to avoid

var x = 1;
if (true) {
    var x = 2;         // SAME x — var ignores block scope
}
console.log(x);        // 2  ← leaked out of the block

⚠️ Why we skip var

var is function-scoped and "hoisted," so it leaks out of blocks and can be used before it's declared. That behavior is a rich source of bugs. You'll still see var in older code — recognize it, but don't write it.

Data Types

Every value in JavaScript has a type. There are two families: primitives (simple, immutable values) and objects (collections that can hold many values).

The seven primitives

TypeExampleWhat it's for
number42, 3.14, -7All numbers — integers and decimals alike
string"hi", `Hi ${name}`Text of any length
booleantrue / falseYes/no, on/off decisions
undefinedlet x;A variable declared but not yet given a value
nulllet y = null;Intentionally "no value"
symbolSymbol("id")Guaranteed-unique keys (advanced)
bigint9007199254740993nIntegers too big for number

Strings & template literals

const firstName = "Ada";
const lastName  = "Lovelace";

// Template literals use backticks and ${ } to embed values:
const fullName = `${firstName} ${lastName}`;   // "Ada Lovelace"
const greeting = `Hello, ${fullName}! You have ${2 + 3} messages.`;

// Handy string methods:
"JavaScript".length;         // 10
"JavaScript".toUpperCase();  // "JAVASCRIPT"
"JavaScript".includes("Scr");// true
"JavaScript".slice(0, 4);    // "Java"

💡 null vs undefined

Think of undefined as "JavaScript hasn't set this yet" and null as "I deliberately set this to empty." A missing object property is undefined; a search that found nothing might return null.

Object types

const person  = { name: "Ada", age: 36 };  // object
const numbers = [1, 2, 3, 4, 5];            // array (a kind of object)
const now     = new Date();                 // date object
function greet(name) { return `Hi ${name}`; } // functions are objects too

Type Conversion & Coercion

Conversion is when you change a type on purpose. Coercion is when JavaScript changes it for you, quietly, to make an operation work. Understanding both prevents a whole category of "why is this a string?!" bugs.

Explicit conversion (you're in control)

Number("123");   // 123
Number("abc");   // NaN  ("Not a Number")
String(123);     // "123"
Boolean("");     // false
Boolean("hi");   // true

Implicit coercion (JavaScript decides)

"5" + 3;   // "53"  ← + with a string means concatenation
"5" - 3;   // 2     ← - has no string meaning, so "5" becomes 5
true + 1;  // 2     ← true becomes 1

⚠️ The + trap

The + operator is the odd one out: if either side is a string, it joins them as text. Every other math operator forces both sides to numbers. When in doubt, convert explicitly.

Operators

Arithmetic

10 + 3;   // 13   addition
10 - 3;   // 7    subtraction
10 * 3;   // 30   multiplication
10 / 3;   // 3.333…  division
10 % 3;   // 1    remainder (modulo) — great for "is it even?"
10 ** 3;  // 1000 exponentiation

Comparison — always use ===

5 == "5";   // true   loose equality coerces types (avoid)
5 === "5";  // false  strict equality checks type AND value (use this)
5 !== "5";  // true   strict inequality
7 > 3;      // true
⚠️ Important: Prefer === and !==. The loose == triggers coercion and produces surprises like 0 == "" being true.

Logical & nullish

true && false;   // false   AND — both must be true
true || false;   // true    OR  — at least one true
!true;           // false   NOT — flips the boolean

// Default values:
const name = userInput || "Guest";  // "" and 0 fall through to default
const count = value ?? 0;           // ?? only defaults on null/undefined

|| vs ??

Use ?? (nullish coalescing) when 0, "", or false are valid values you want to keep. count || 10 wrongly replaces a real 0; count ?? 10 keeps it.

Ternary — a compact if/else

const age = 20;
const status = age >= 18 ? "adult" : "minor";   // "adult"

Checking Types

Use typeof to inspect a value's type — with two famous quirks to memorize.

typeof 42;          // "number"
typeof "hi";        // "string"
typeof true;        // "boolean"
typeof undefined;   // "undefined"
typeof null;        // "object"   ← a historical bug, kept for compatibility
typeof [];          // "object"   ← arrays report as objects
typeof function(){};// "function"

// For the two quirks, use purpose-built checks:
Array.isArray([]);        // true
value === null;           // reliable null check

Output

typeof null → "object"   // yes, really
Array.isArray([1,2]) → true

Practice & Quiz

🏋️ Exercise 1: A type checker

Goal: Write describeType(value) that returns a clean type name, correctly handling arrays and null.

function describeType(value) {
    // TODO: return "array", "null", or the typeof for everything else
}
console.log(describeType([1, 2]));   // should log: "array"
console.log(describeType(null));     // should log: "null"
console.log(describeType(42));       // should log: "number"
💡 Hint

Check Array.isArray(value) first, then value === null, then fall back to typeof value.

✅ Solution
function describeType(value) {
    if (Array.isArray(value)) return "array";
    if (value === null) return "null";
    return typeof value;
}

🏋️ Exercise 2: Temperature converter

Goal: Convert Celsius to Fahrenheit, formatted to two decimals.

✅ Solution
function cToF(celsius) {
    const f = celsius * 9 / 5 + 32;
    return `${f.toFixed(2)}°F`;
}
console.log(cToF(100));  // "212.00°F"
console.log(cToF(37));   // "98.60°F"

🎯 Quick Quiz

Question 1: Which keyword should you reach for first when declaring a variable?

Question 2: What does "5" + 3 evaluate to?

Question 3: What is typeof null?

Best Practices & Pitfalls

✅ Do

  • Default to const; use let only when reassigning
  • Always compare with === / !==
  • Name variables clearly: isActive, userCount, MAX_SIZE
  • Convert types explicitly when it matters

❌ Don't

  • Write new code with var
  • Rely on == and hope the coercion works out
  • Compare with NaN using ===NaN === NaN is false; use Number.isNaN()

⚠️ Floating-point surprise

0.1 + 0.2;            // 0.30000000000000004
0.1 + 0.2 === 0.3;    // false!

Binary floating point can't represent every decimal exactly. For money, work in whole cents (integers) or use a decimal library.

Naming conventions

let firstName = "Ada";        // camelCase for variables & functions
const MAX_SIZE = 100;         // UPPER_SNAKE_CASE for fixed constants
class UserProfile {}          // PascalCase for classes
let isActive = true;          // is/has prefix for booleans

Summary

🎉 Key Takeaways

  • Load JavaScript from an external file with defer for real projects
  • Declare with const by default, let when it changes, never var
  • There are seven primitive types plus objects (including arrays and functions)
  • JavaScript will coerce types for you — + is the one that concatenates
  • Compare with ===, and know the typeof null === "object" quirk

📚 Additional Resources

🚀 What's Next?

Now that you can store and compare data, the next lesson gives your programs the power to make decisions and repeat work: Control Structures — Conditionals and Loops.

🎉 Nicely done!

You've written your first real JavaScript. Everything interactive you build from here stands on these fundamentals.