JavaScript Fundamentals

Introduction

So far you have used HTML to define page structure and CSS to control appearance. Neither can make a page do anything. For interactivity – responding to clicks, validating forms, fetching data – you need JavaScript.

The Three Languages of the Web:

  HTML          CSS           JavaScript
┌──────────┐  ┌──────────┐  ┌──────────┐
│Structure │  │  Style   │  │ Behavior │
│ headings │  │  colors  │  │  clicks  │
│  lists   │  │  fonts   │  │  forms   │
│  links   │  │  layout  │  │  data    │
└──────────┘  └──────────┘  └──────────┘
   bones         skin         muscles

JavaScript is the only programming language that runs natively in browsers. Created in 1995, it now powers everything from form validation to complex applications like Gmail and the React apps you will build later in this course.


The Browser Console

The fastest way to start writing JavaScript is the browser console – a built-in tool where you can type code and see results instantly.

Open DevTools

  • Mac: Cmd + Option + I
  • Windows/Linux: F12 or Ctrl + Shift + I

Go to the Console Tab

Click the Console tab at the top of the DevTools panel.

Type Your First Command

console.log("Hello, World!");

Press Enter. You should see Hello, World! printed below.

Experiment

2 + 2
"Hello" + " " + "World"
Math.random()
console.log() prints a value to the console. Think of it as “show me what this value is.” You will use it constantly for testing and debugging.

Connecting JavaScript to HTML

Real JavaScript lives in .js files linked to your HTML with the <script> tag:

<body>
    <h1>Hello!</h1>
    <!-- Add script at end of body -->
    <script src="script.js"></script>
</body>
Place <script> at the end of <body>. This ensures all HTML elements are loaded before your JavaScript runs.
    • index.html
    • style.css
    • script.js

  • Variables

    A variable is a named container that stores a value. JavaScript has two modern keywords for creating variables:

    const name = "Alice";   // Cannot be reassigned
    let score = 85;         // Can be reassigned
    
    score = 90;             // OK -- let allows this
    // name = "Bob";        // ERROR -- const prevents this
    
    KeywordCan Reassign?When to Use
    constNoDefault choice. Use for values that won’t change.
    letYesOnly when the value needs to change later.
    varYesNever. Old syntax (pre-2015) with confusing behavior.
    Use const by default. Only use let when you have a specific reason the value needs to change. Never use var.

    Naming Conventions

    • Use camelCase: firstName, totalScore, isLoggedIn
    • Must start with a letter, _, or $
    • Names are case-sensitive (score and Score are different)
    // Good:
    const firstName = "Alice";
    const isLoggedIn = true;
    
    // Bad:
    const x = "Alice";          // Too vague
    const first_name = "Alice"; // snake_case is not the JS convention
    

    Data Types

    Every value in JavaScript has a type that determines how it behaves.

    String – text data, wrapped in quotes.

    const greeting = "Hello, World!";   // Double quotes
    const name = 'Alice';               // Single quotes
    const message = `Score: ${95}`;     // Backticks (template literal)
    
    console.log(typeof greeting); // "string"
    

    Useful string methods:

    const text = "JavaScript";
    text.length              // 10
    text.toUpperCase()       // "JAVASCRIPT"
    text.includes("Script")  // true
    

    Number – any numeric value (integer or decimal).

    const age = 25;
    const price = 9.99;
    
    console.log(typeof age); // "number"
    

    JavaScript does not distinguish between integers and decimals – they are all number.

    Special values: Infinity, -Infinity, NaN (“Not a Number” – result of invalid math like "abc" * 2).

    Booleantrue or false. The foundation of conditional logic.

    const isLoggedIn = true;
    const isAdult = age >= 18; // true or false depending on age
    
    console.log(typeof isLoggedIn); // "boolean"
    

    null – intentionally empty. You set this deliberately.

    undefined – not yet assigned. JavaScript sets this automatically.

    let selectedUser = null;  // "I set this to nothing on purpose"
    let score;                // undefined -- "no value assigned yet"
    
    null:       "The box is intentionally empty"
                ┌──────────┐
                │  (empty) │  <-- You put nothing in it on purpose
                └──────────┘
    
    undefined:  "The box was never opened"
                ┌──────────┐
                │    ???   │  <-- No value assigned yet
                └──────────┘

    Template Literals

    Template literals use backticks and ${expression} to embed values in strings:

    const name = "Alice";
    const age = 20;
    
    // Old way (concatenation):
    console.log("Name: " + name + ", Age: " + age);
    
    // Modern way (template literals):
    console.log(`Name: ${name}, Age: ${age}`);
    console.log(`Next year: ${age + 1}`);
    Where is the backtick key? Below the Esc key on most keyboards, on the same key as the tilde (~).

    The typeof Operator

    typeof "hello"      // "string"
    typeof 42           // "number"
    typeof true         // "boolean"
    typeof undefined    // "undefined"
    typeof null         // "object"  <-- Famous JS bug!
    
    typeof null returns "object" instead of "null". This is a known bug from 1995 that was never fixed.

    Operators

    Arithmetic Operators

    OperatorNameExampleResult
    +Addition10 + 313
    -Subtraction10 - 37
    *Multiplication10 * 330
    /Division10 / 33.333...
    %Remainder10 % 31
    **Exponentiation2 ** 38
    let count = 10;
    count += 5;    // count = count + 5  (now 15)
    count -= 3;    // count = count - 3  (now 12)
    count++;       // count = count + 1  (now 13)
    

    Comparison Operators

    OperatorNameExampleResult
    ===Strict equality5 === 5true
    !==Strict inequality5 !== 3true
    >Greater than5 > 3true
    <Less than5 < 3false
    >=Greater or equal5 >= 5true
    <=Less or equal5 <= 3false

    NEVER use == or !=. ALWAYS use === and !==.

    Double equals (==) converts types before comparing, causing bugs:

    5 == "5"     // true   WRONG -- a number should not equal a string
    0 == false   // true   WRONG -- zero should not equal false
    
    5 === "5"    // false  CORRECT -- different types are not equal
    0 === false  // false  CORRECT
    

    Triple equals (===) checks both value AND type – always use it.

    Logical Operators

    OperatorNameMeaning
    &&ANDBoth must be true
    ||ORAt least one must be true
    !NOTFlips the value
    const age = 20;
    const hasID = true;
    
    if (age >= 18 && hasID) {
        console.log("Entry allowed");  // Both true
    }
    
    if (!hasID) {
        console.log("ID required");    // Runs if hasID is false
    }

    Type Coercion

    JavaScript sometimes converts types automatically, which can be surprising:

    "5" + 3    // "53"  (string wins -- concatenation)
    "5" - 3    // 2     (math wins -- subtraction)
    

    The + operator can mean concatenation or addition. When one side is a string, it concatenates. The -, *, / operators only do math, so they convert strings to numbers.

    You do not need to memorize coercion rules. Just use === and be careful with + on mixed types.

    Functions

    A function is a reusable block of code. Instead of repeating the same logic, you write it once and call it whenever needed.

      Input (Parameters)    Function Body       Output (Return Value)
      ┌───────────┐      ┌──────────────┐     ┌───────────┐
      │ name      │─────>│ process the  │────>│  result   │
      │ score     │      │ data         │     └───────────┘
      └───────────┘      └──────────────┘

    Three Ways to Define Functions

    Function Declaration – the classic way.

    function greet(name) {
      return `Hello, ${name}!`;
    }
    
    greet("Alice"); // "Hello, Alice!"
    
    • Uses the function keyword
    • Can be called before its definition (hoisting)

    Function Expression – stored in a variable.

    const greet = function(name) {
      return `Hello, ${name}!`;
    };
    
    greet("Alice"); // "Hello, Alice!"
    
    • Assigned to a const variable
    • Cannot be called before its definition

    Arrow Function – modern, concise.

    // Full form:
    const greet = (name) => {
      return `Hello, ${name}!`;
    };
    
    // Short form (implicit return):
    const greet = (name) => `Hello, ${name}!`;
    
    greet("Alice"); // "Hello, Alice!"
    
    • Uses => (the “fat arrow”)
    • One-liner? Omit {} and return for implicit return
    • Preferred for short functions

    Same function, three ways:

    function double(n) { return n * 2; }          // Declaration
    const double = function(n) { return n * 2; };  // Expression
    const double = (n) => n * 2;                   // Arrow
    // All three: double(5) returns 10
    
    Which to use? Arrow functions for short functions. Declarations for longer, named functions. Expressions are less common but you will encounter them.

    Parameters and Return Values

    // Two parameters, one return:
    const add = (a, b) => a + b;
    add(5, 3); // 8
    
    // No parameters:
    const sayHi = () => console.log("Hi!");
    
    // Multiple statements need {} and explicit return:
    const calculate = (a, b) => {
        const sum = a + b;
        const product = a * b;
        return { sum, product };
    };

    Default Parameters

    const greet = (name = "World") => `Hello, ${name}!`;
    
    greet("Alice"); // "Hello, Alice!"
    greet();        // "Hello, World!"
    

    Conditionals

    Conditionals let your code make decisions based on whether a condition is true or false.

    if / else / else if

    const score = 85;
    
    if (score >= 90) {
        console.log("Grade: A");
    } else if (score >= 80) {
        console.log("Grade: B");
    } else if (score >= 70) {
        console.log("Grade: C");
    } else {
        console.log("Grade: F");
    }
    // Output: "Grade: B"
    
    How if/else evaluates (score = 85):
    
      score >= 90?  ── NO ────┐
                               ▼
      score >= 80?  ── YES ──> Run this block ("Grade: B")
                               │
      score >= 70?  ── SKIP ──┘
      else          ── SKIP

    Ternary Operator

    A shorthand for simple two-way if/else:

    // condition ? valueIfTrue : valueIfFalse
    
    const age = 20;
    const status = age >= 18 ? "Adult" : "Minor";
    // Same as: if (age >= 18) { status = "Adult"; } else { status = "Minor"; }
    
    Only use ternary for simple, two-way choices. For complex logic, use if/else – readability matters more than brevity.

    Preview: Arrays

    Arrays are covered fully in Week 6. Here is a brief introduction.

    An array is an ordered list of values, where each item has a position (index) starting at 0.

    const colors = ["red", "green", "blue"];
    
    colors[0]       // "red"
    colors[1]       // "green"
    colors.length   // 3
    
    colors.push("yellow"); // Add to end
    colors.forEach((color) => console.log(color)); // Loop through
    

    Preview: Objects

    Also covered fully in Week 6. An object is a collection of key-value pairs.

    const student = {
        name: "Alice",
        age: 20,
        major: "Computer Science"
    };
    
    student.name           // "Alice" (dot notation)
    student["age"]         // 20 (bracket notation)
    student.age = 21;      // Modify a property
    
    Even though student is declared with const, you can change its properties. const prevents reassigning the variable itself, not modifying its contents.

    Preview: Loops

    Full coverage in Week 6. Here are the basics.

    // for loop:
    for (let i = 0; i < 5; i++) {
        console.log(`Iteration ${i}`);
    }
    
    // for...of (loop through array values):
    const colors = ["red", "green", "blue"];
    for (const color of colors) {
        console.log(color);
    }

    Common Patterns

    Function Returning Different Values Based on Input

    const getGrade = (score) => {
        if (score >= 90) return "A";
        if (score >= 80) return "B";
        if (score >= 70) return "C";
        if (score >= 60) return "D";
        return "F";
    };

    No else needed when each branch uses return – the function exits immediately.

    Template Literal for Formatted Output

    const formatPrice = (name, price, qty) => {
        const total = price * qty;
        return `${name} x${qty}: $${total.toFixed(2)}`;
    };
    formatPrice("Widget", 9.99, 3); // "Widget x3: $29.97"
    

    Complete Report (Combines Everything)

    const printReport = (name, score) => {
        const grade = getGrade(score);
        const passing = grade !== "F" ? "Passing" : "Failing";
    
        console.log("=== Grade Report ===");
        console.log(`Student: ${name}`);
        console.log(`Score: ${score}, Grade: ${grade}`);
        console.log(`Status: ${passing}`);
        console.log("====================");
    };
    
    printReport("Alice", 95);
    printReport("Bob", 55);

    Troubleshooting & Common Mistakes

    ReferenceError: x is not defined

    You are using a variable that does not exist. Check for typos, and remember JavaScript is case-sensitive (userName vs username).

    // FIX: Declare the variable before using it
    const userName = "Alice";
    console.log(userName);
    TypeError: x is not a function

    You are trying to call something that is not a function. Check that you did not accidentally overwrite a function name with a non-function value.

    // WRONG:
    const greet = "Hello";
    greet("Alice"); // TypeError!
    
    // FIX:
    const greet = (name) => `Hello, ${name}!`;
    TypeError: Assignment to constant variable

    You tried to reassign a const variable. Use let if the value needs to change.

    // WRONG:
    const score = 85;
    score = 90; // TypeError!
    
    // FIX:
    let score = 85;
    score = 90; // OK
    
    SyntaxError: Unexpected token

    Usually means a typo: missing parenthesis, extra bracket, or using = instead of ===.

    // WRONG:
    if (score = 90) { ... }  // Assigns 90 to score!
    
    // FIX:
    if (score === 90) { ... }
    Function returns undefined

    With curly braces in arrow functions, you must use return. Without curly braces, return is implicit.

    // WRONG (no return):
    const double = (n) => { n * 2; };
    double(5); // undefined
    
    // FIX:
    const double = (n) => { return n * 2; };
    // Or:
    const double = (n) => n * 2;
    NaN showing up unexpectedly

    A math operation received a non-numeric value. Make sure your variables hold numbers before doing math.

    "hello" * 5         // NaN
    undefined + 1       // NaN
    Number("10") + 5    // 15 (convert string to number first)
    

    Key Takeaways

    🎯
    • JavaScript adds behavior to web pages – HTML is structure, CSS is style, JS is interactivity
    • The browser console (F12) is your best tool for learning and testing
    • Use const by default, let when needed, never var
    • Five basic data types: string, number, boolean, null, undefined
    • Template literals use backticks and ${expression} for cleaner strings
    • Always use === for comparison (never ==)
    • Arrow functions (=>) are the modern default for short functions
    • if/else for branching, ternary for simple two-way choices
    • With {} in arrow functions, you must write return explicitly

    Additional Resources

    Official Documentation

    Interactive Tutorials

    Practice & Exploration